/// <summary> /// Get type of two /// </summary> /// <param name="second">Second type which compares</param> /// <returns>Main type</returns> private JType GetEitherType(JType second) { var sub = Either(this, second); if (Type == JTypeEnum.Array) { if (second.IsNull) { return(this); } if (IsNull) { return(second); } var locale = SubType.GetEitherType(second.SubType).GetEitherType(CreateNull()); if (locale != SubType) { return new JType { Type = JTypeEnum.Array, SubType = locale } } ; } if (Type == sub.Type) { return(this); } return(sub.GetEitherType(CreateNull())); }
/// <summary> /// Get similar types /// </summary> /// <param name="first">First type</param> /// <param name="second">Second type</param> /// <returns>True, if first type is similar to second, otherwise no</returns> private static bool IsRelatedValues(JType first, JType second) { var f = first.Type == JTypeEnum.Int || first.Type == JTypeEnum.Long || first.Type == JTypeEnum.Float || first.Type == JTypeEnum.Double; var s = second.Type == JTypeEnum.Int || second.Type == JTypeEnum.Long || second.Type == JTypeEnum.Float || second.Type == JTypeEnum.Double; return(f == s); }
/// <summary> /// Get type of two /// </summary> /// <param name="first">First item</param> /// <param name="second">Second item</param> /// <returns>Main JType</returns> private static JType Either(JType first, JType second) { if (first.IsNull) { return(second); } if (second.IsNull) { return(first); } switch (first.Type) { case JTypeEnum.RandomType: if (IsRandom(second)) { first.Type = second.Type; } return(first); case JTypeEnum.String: case JTypeEnum.Bool: case JTypeEnum.DateTime: case JTypeEnum.Object: case JTypeEnum.Array: case JTypeEnum.Int: case JTypeEnum.Long: case JTypeEnum.Float: case JTypeEnum.Double: if (IsRelatedValues(first, second)) { first.Type = second.Type; } return(first); default: return(new JType { IsNull = true, Type = JTypeEnum.RandomType }); } }
/// <summary> /// Parse from json /// </summary> /// <param name="json">Json string</param> /// <param name="rootName">RootName of object</param> /// <returns>Main data of parse</returns> public ParserData Parse(string json, string rootName = "ROOTBITCH") { Init(); JObject[] examples = new JObject[0]; JToken j = JToken.Parse(json); if (j is JArray) { examples = ((JArray)j).Cast <JObject>().ToArray(); } else if (j is JObject) { examples = new[] { j as JObject }; } else { throw new Exception("Sample JSON must be either a JSON array, or a JSON object."); } MainType = JType.Create(examples[0]); MainType.Name = rootName; MakeData(examples, MainType); return(GetData()); }
/// <summary> /// Create JType from JToken /// </summary> /// <param name="token">Parsed from json</param> /// <returns>Main JType</returns> public static JType Create(JToken token) { JType j = new JType(); switch (token.Type) { case JTokenType.Integer: if ((long)((JValue)token).Value < int.MaxValue) { j.Type = JTypeEnum.Int; } else { j.Type = JTypeEnum.Long; } break; case JTokenType.Float: if ((double)((JValue)token).Value < float.MaxValue) { j.Type = JTypeEnum.Float; } else { j.Type = JTypeEnum.Double; } break; case JTokenType.Array: j.Type = JTypeEnum.Array; break; case JTokenType.Object: j.Type = JTypeEnum.Object; break; case JTokenType.Comment: case JTokenType.String: j.Type = JTypeEnum.String; break; case JTokenType.Boolean: j.Type = JTypeEnum.Bool; break; case JTokenType.Null: case JTokenType.Undefined: case JTokenType.None: j.IsNull = true; break; case JTokenType.Date: j.Type = JTypeEnum.DateTime; break; default: j.Type = JTypeEnum.RandomType; break; } if (j.Type == JTypeEnum.Array) { var array = (JArray)token; j.SubType = GetSubType(array.ToArray()); } return(j); }
/// <summary> /// Is random type OR is unknown type /// </summary> /// <param name="val">Main Type</param> /// <returns>True, if type is unknown type, otherwise no</returns> private static bool IsRandom(JType val) { return(val.Type == JTypeEnum.String || val.Type == JTypeEnum.Int || val.Type == JTypeEnum.Float || val.Type == JTypeEnum.Double || val.Type == JTypeEnum.Long || val.Type == JTypeEnum.Bool || val.Type == JTypeEnum.DateTime || val.Type == JTypeEnum.Array || val.Type == JTypeEnum.Object); }
/// <summary> /// Create root /// </summary> /// <param name="examples">Items</param> /// <param name="main">Main Jtype</param> private void MakeData(JObject[] examples, JType main) { foreach (var item in examples) { foreach (var property in item.Properties()) { if (main.SubTypes.SingleOrDefault(x => x.Name == property.Name) == null) { var rt = JType.Create(property.Value); rt.Name = property.Name; if (!main.SubTypes.Contains(rt)) { main.SubTypes.Add(rt); } } } } foreach (var item in main.SubTypes) { if (item.Type == JTypeEnum.Object) { var subexamples = new List <JObject>(examples.Length); foreach (var objc in examples) { JToken value; if (objc.TryGetValue(item.Name, out value)) { if (value.Type == JTokenType.Object) { subexamples.Add((JObject)value); } } } if (!_localData.Names.Contains(item.Name)) { _localData.Names.Add(item.Name); MakeData(subexamples.ToArray(), item); } } if (item.SubType?.Type == JTypeEnum.Object) { var subexamples = new List <JObject>(examples.Length); foreach (var obj in examples) { JToken value; if (obj.TryGetValue(item.Name, out value)) { if (value.Type == JTokenType.Array) { foreach (var itemValue in (JArray)value) { if (!(itemValue is JObject)) { throw new NotSupportedException("Arrays of non-objects are not supported yet."); } subexamples.Add((JObject)itemValue); } } else if (value.Type == JTokenType.Object) { foreach (var itemValue in (JObject)value) { if (!(itemValue.Value is JObject)) { throw new NotSupportedException("Arrays of non-objects are not supported yet."); } subexamples.Add((JObject)itemValue.Value); } } } } item.SubType.Name = item.Name; MakeData(subexamples.ToArray(), item.SubType); } } _localData.Types.Add(main); }