Generate a JsonSchema from a c# class including conditional member setters logic

190 Views Asked by At

I Have the following Class

Class Creature
    {
         public string Name {get; set;}
         private string _clss;
         public string Clss 
         {
            get {return _clss} 
            set 
            {
                if(Mapping.dic.ContainsKey(value))
                {
                    _clss = value;
                }
            }
         }
         private List<string> _specs = new List<string>();
         public List<string> Specs
         {
            get {return _specs}
            set
            {
                if(Mapping.dic.ContainsKey(value))
                {
                    foreach(var item in value)
                    {
                       if(Mapping.dic[this.Clss].Contains(item)
                       {
                          _specs.Add(item);
                       }
                    }
                }
         }
    }

And i have the following dictionary in a static class that i use for mapping

static class Mapping
{
   public static Dictionary<string,HashSet<string>> dic
   {
       get
       {
          Dictionary<string, HashSet<string>> dic = new Dictionary<string, HashSet<string>>();
          dic.Add("Mage", new HashSet<string>() {"magic", "fast", "old"});
          dic.Add("Monster", new HashSet<string>() {"magic", "strong"});
          dic.Add("Warrior", new HashSet<string>() {"strong", "old","slow"});
          return dic;
       }
   }
}

using NJsonSchema to generate a schema for the Creature class will result in a schema that won't include any representation of the logic that's defined in the custom setters code

var schema = JsonSchema.FromType(typeof(Creature));
var data = schema.ToJson();

the result schema would be:

{
   "$schema": "http://json-schema.org/draft-04/schema#",
   "title": "Creature",
   "type": "object",
   "additionalProperties": false,
   "properties": {
   "Name": {
     "type": "string"
   },
   "Clss": {
     "type": "string"
   },
   "Specs": {
     "type": "array",
     "items": {
        "type": "string"
     }
   }
  }
}

now i tried with a reverse process where i wrote the Schema first and generate the C# class from it using the NJsonSchema code generator

the manually generated schema :

   {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "Creature",
      "type": "object",
      "properties": {
        "Clss": {
          "type": "string",
          "enum": ["Mage", "Monster", "Warrior"]
        },
        "Specs": {
          "type": "string"
        }
      },
      "required": ["Clss", "Specs"],
      "dependencies": {
        "Specs": {
          "oneOf": [
            {
              "properties": {
                "Clss": { "const": "Mage" },
                "Specs": { "enum": ["magic", "fast", "old"] }
              }
            },
            {
              "properties": {
                "Clss": { "const": "Monster" },
                "Specs": { "enum": ["magic", "strong"] }
              }
            },
            {
              "properties": {
                "Clss": { "const": "Warrior" },
                "Specs": { "enum": ["strong", "old", "slow"] }
              }
            }
          ]
        }
      }
    }

when passed to a c# code generator using the following logic

    string JsonString = "" // the json goes here formating this is pain and the post is long already 
    var sc = await JsonSchema.FromJsonAsync(JsonString);
    var generator = new CSharpGenerator(sc);
    var file = generator.GenerateFile();

the generated C# class :

//----------------------
// <auto-generated>
//     Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v13.0.0.0) (http://NJsonSchema.org)
// </auto-generated>
//----------------------


namespace MyNamespace
{
    #pragma warning disable // Disable all warnings

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.9.0.0 (Newtonsoft.Json v13.0.0.0)")]
    public partial class Anonymous
    {
        [Newtonsoft.Json.JsonProperty("clss", Required = Newtonsoft.Json.Required.Always)]
        [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
        [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
        public Clss Clss { get; set; }

        [Newtonsoft.Json.JsonProperty("specs", Required = Newtonsoft.Json.Required.Always)]
        [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
        public string Specs { get; set; }



        private System.Collections.Generic.IDictionary<string, object> _additionalProperties;

        [Newtonsoft.Json.JsonExtensionData]
        public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
        {
            get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>()); }
            set { _additionalProperties = value; }
        }

    }

    [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.9.0.0 (Newtonsoft.Json v13.0.0.0)")]
    public enum Clss
    {

        [System.Runtime.Serialization.EnumMember(Value = @"Mage")]
        Mage = 0,


        [System.Runtime.Serialization.EnumMember(Value = @"Monster")]
        Monster = 1,


        [System.Runtime.Serialization.EnumMember(Value = @"Warrior")]
        Warrior = 2,


    }
}

so my questions are :

  1. Is what i am trying to achieve feasible "C# to Json Schema including the custom logic"?
  2. How can i generate a schema with the desired logic using NJsonSchema or any other nuget?
  3. Are there any alternative approaches or methods? i am open to any implementation that achieve the desired output "other than manually editing/Hard coding the generated JSON".
0

There are 0 best solutions below