Advertisement
LaughingMan

Json Schema Discovery

Dec 18th, 2015
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.42 KB | None | 0 0
  1. public static class JsonHelper
  2.     {
  3.         static JsonHelper()
  4.         {
  5.             GlobalSchemas = new Dictionary<string, Dictionary<string, object>>();
  6.         }
  7.  
  8.         public static Dictionary<string, Dictionary<string, object>> GlobalSchemas { get; set; }
  9.  
  10.         public static object ProcessJsonSchema(string response)
  11.         {
  12.             if (response.IsNullOrWhiteSpace())
  13.             {
  14.                 return null;
  15.             }
  16.  
  17.             response = response.Replace("\r", "").Replace("\n", "").Trim();
  18.  
  19.             if (response.StartsWith("//"))
  20.             {
  21.                 response = response.Trim('/', '[');
  22.             }
  23.  
  24.             // Convert hex values (eg. "\x2F") to their string character equivalent (eg. "/")
  25.             for (var i = 0; i < 128; i++)
  26.             {
  27.                 var hexString = i.ToString("X").PadLeft(2, '0');
  28.                 var searchString = @"\x" + hexString;
  29.                 var charValue = Convert.ToInt32(hexString, 16);
  30.                 var character = char.ConvertFromUtf32(charValue);
  31.  
  32.                 response = response.Replace(searchString, character == "\""
  33.                     ? "'"
  34.                     : character);
  35.             }
  36.  
  37.             var token = JToken.Parse(response);
  38.  
  39.             var schema = ProcessJToken(token);
  40.  
  41.             AddToGlobalSchema(schema, "StockData");
  42.  
  43.             return schema;
  44.         }
  45.  
  46.         private static Dictionary<string, object> ProcessJObject(JObject jObject)
  47.         {
  48.             return ProcessJObject(jObject.ToString());
  49.         }
  50.  
  51.         private static Dictionary<string, object> ProcessJObject(string input)
  52.         {
  53.             //IDictionary<string, JToken> properties = JSchema.Parse(input).ExtensionData;
  54.             IDictionary<string, JToken> properties = JsonConvert.DeserializeObject<Dictionary<string, JToken>>(input);
  55.             var fields = new Dictionary<string, object>();
  56.  
  57.             foreach (var property in properties)
  58.             {
  59.                 var schema = ProcessJToken(property.Value);
  60.                 fields.Add(property.Key, schema);
  61.             }
  62.  
  63.             return fields;
  64.         }
  65.  
  66.         private static object ProcessJToken(JToken token)
  67.         {
  68.             if (token == null)
  69.                 return null;
  70.  
  71.             switch (token.Type)
  72.             {
  73.                 case JTokenType.Object:
  74.                     var jObject = (JObject)token;
  75.                     var objectResult = ProcessJObject(jObject);
  76.                     return objectResult;
  77.                 case JTokenType.Array:
  78.                     var array = (JArray)token;
  79.                     var arrayResult = array.Select(ProcessJToken);
  80.                     return arrayResult;
  81.                 case JTokenType.Property:
  82.                     var property = (JProperty)token;
  83.                     var propertyResult = ProcessJToken(property.Value);
  84.                     return propertyResult;
  85.                 case JTokenType.Raw:
  86.                 case JTokenType.Uri:
  87.                 case JTokenType.Comment:
  88.                 case JTokenType.Constructor:
  89.                 case JTokenType.None:
  90.                 case JTokenType.Undefined:
  91.                     return JTokenType.String;
  92.                 case JTokenType.Null:
  93.                     return null;
  94.                 case JTokenType.Integer:
  95.                 case JTokenType.Float:
  96.                 case JTokenType.String:
  97.                 case JTokenType.Boolean:
  98.                 case JTokenType.Date:
  99.                 case JTokenType.Bytes:
  100.                 case JTokenType.Guid:
  101.                 case JTokenType.TimeSpan:
  102.                     return token.Type;
  103.                 default:
  104.                     throw new ArgumentOutOfRangeException();
  105.             }
  106.         }
  107.  
  108.         private static void AddToGlobalSchema(object schema, string name)
  109.         {
  110.             if (schema == null)
  111.                 return;
  112.  
  113.             name = name.IfNullOrWhiteSpace("JsonObject");
  114.  
  115.             if (!GlobalSchemas.ContainsKey(name))
  116.             {
  117.                 GlobalSchemas.Add(name, new Dictionary<string, object>());
  118.             }
  119.  
  120.             var globalSchema = GlobalSchemas[name] ?? new Dictionary<string, object>();
  121.  
  122.             var isArray = schema is IEnumerable<object>;
  123.             var isModel = schema is Dictionary<string, object>;
  124.  
  125.             if (isArray)
  126.             {
  127.                 // Array
  128.                 var objects = schema as IEnumerable<object>;
  129.  
  130.                 foreach (var obj in objects)
  131.                 {
  132.                     AddToGlobalSchema(obj, name);
  133.                 }
  134.             }
  135.             else if (isModel)
  136.             {
  137.                 // Object
  138.                 var fields = (Dictionary<string, object>)schema;
  139.  
  140.                 foreach (var field in fields)
  141.                 {
  142.                     if (field.Key.IsNullOrWhiteSpace() || field.Value == null)
  143.                         continue;
  144.  
  145.                     var ismodel = field.Value is Dictionary<string, object>;
  146.                     var isarray = field.Value is IEnumerable<object>;
  147.  
  148.                     var fieldName = field.Key + (isarray ? "Array" : "");
  149.                     var isnew = !globalSchema.ContainsKey(fieldName);
  150.  
  151.                     if (isnew)
  152.                     {
  153.                         if (ismodel)
  154.                         {
  155.                             globalSchema.Add(fieldName, fieldName);
  156.                             AddToGlobalSchema(field.Value as Dictionary<string, object>, field.Key);
  157.                         }
  158.                         else if (isarray)
  159.                         {
  160.                             globalSchema.Add(fieldName, string.Format("Collection<{0}>", field.Key));
  161.  
  162.                             var objects = ((IEnumerable<object>)field.Value).ToArray();
  163.  
  164.                             if (!objects.Any())
  165.                                 continue;
  166.  
  167.                             foreach (var obj in objects)
  168.                             {
  169.                                 AddToGlobalSchema(obj, field.Key);
  170.                             }
  171.                         }
  172.                         else
  173.                         {
  174.                             globalSchema.Add(field.Key, field.Value);
  175.                         }
  176.                     }
  177.                     else
  178.                     {
  179.                         if (ismodel)
  180.                         {
  181.                             if (!globalSchema[fieldName].Equals(fieldName))
  182.                             {
  183.                                 globalSchema[fieldName] = fieldName;
  184.                             }
  185.                             AddToGlobalSchema(field.Value as Dictionary<string, object>, fieldName);
  186.                         }
  187.                         else if (isarray)
  188.                         {
  189.                             if (!globalSchema[fieldName].Equals(string.Format("Collection<{0}>", field.Key)))
  190.                             {
  191.                                 globalSchema[fieldName] = string.Format("Collection<{0}>", field.Key);
  192.                             }
  193.  
  194.                             var objects = ((IEnumerable<object>)field.Value).ToArray();
  195.  
  196.                             foreach (var obj in objects)
  197.                             {
  198.                                 AddToGlobalSchema(obj, field.Key);
  199.                             }
  200.                         }
  201.                         else
  202.                         {
  203.                             if (!globalSchema[fieldName].Equals(field.Value))
  204.                             {
  205.                                 globalSchema[fieldName] = field.Value;
  206.                             }
  207.                         }
  208.                     }
  209.                 }
  210.  
  211.                 GlobalSchemas[name] = globalSchema;
  212.             }
  213.             else
  214.             {
  215.                 // ?
  216.                 Debug.WriteLine(schema);
  217.             }
  218.         }
  219.  
  220.         public static string OutputGlobalSchema()
  221.         {
  222.             if (GlobalSchemas == null || !GlobalSchemas.Any())
  223.                 return null;
  224.            
  225.             var output = "";
  226.             foreach (var schema in GlobalSchemas)
  227.             {
  228.                 output += string.Format("public class {0}\r\n{{", schema.Key);
  229.                 var schemaValue = schema.Value
  230.                                         .OrderBy(o => o.Value.ToString().StartsWith("Collection"))
  231.                                         .ThenBy(t => t.Value.ToString())
  232.                                         .ThenBy(t => t.Key);
  233.  
  234.                 foreach (var field in schemaValue)
  235.                 {
  236.                     string fieldName = field.Key;
  237.                     string fieldValue = field.Value.ToString();
  238.  
  239.                     switch (fieldValue)
  240.                     {
  241.                         case "String":
  242.                             fieldValue = "string";
  243.                             break;
  244.                         case "Integer":
  245.                             fieldValue = "int?";
  246.                             break;
  247.                         case "Decimal":
  248.                             fieldValue = "decimal?";
  249.                             break;
  250.                         case "Float":
  251.                             fieldValue = "float?";
  252.                             break;
  253.                         case "Date":
  254.                             fieldValue = "DateTime?";
  255.                             break;
  256.                         case "TimeSpan":
  257.                             fieldValue = "TimeSpan?";
  258.                             break;
  259.                         case "Boolean":
  260.                             fieldValue = "bool?";
  261.                             break;
  262.                         case "Bytes":
  263.                             fieldValue = "byte[]";
  264.                             break;
  265.                     }
  266.  
  267.                     if (fieldName.EndsWith("Array") || fieldValue.StartsWith("Collection"))
  268.                     {
  269.                         fieldName = fieldName.Replace("Array", "");
  270.                         string modelName = fieldValue.Replace("Collection", "").Trim('<', '>');
  271.  
  272.                         bool isValueArray = !GlobalSchemas.ContainsKey(modelName);
  273.  
  274.                         if (fieldValue.StartsWith("Collection") && isValueArray)
  275.                         {
  276.                             output += string.Format("\r\n\t[JsonProperty(PropertyName=\"{0}\")]", fieldName);
  277.                             output += string.Format("\r\n\tpublic string V_{0} {{ get; set; }}", fieldName);
  278.                             output += string.Format("\r\n\r\n\t[NotMapped]\r\n\tpublic string[] V_{0}Values {{ get {{ return V_{0}.Split(','); }} set{{ V_{0} = string.Join(\", \", value); }} }}\r\n", fieldName);
  279.                         }
  280.                         else
  281.                         {
  282.                             output += string.Format("\r\n\t[JsonProperty(PropertyName=\"{0}\")]", fieldName);
  283.                             output += string.Format("\r\n\tpublic {0} V_{1} {{ get; set; }}\r\n", fieldValue, field.Key);
  284.                         }
  285.                        
  286.                     }
  287.                     else
  288.                     {
  289.                         output += string.Format("\r\n\t[JsonProperty(PropertyName=\"{0}\")]", fieldName);
  290.                         output += string.Format("\r\n\tpublic {0} V_{1} {{ get; set; }}\r\n", fieldValue, field.Key);
  291.                     }
  292.                 }
  293.  
  294.                 output += "}\r\n";
  295.             }
  296.  
  297.             return output;
  298.         }
  299.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement