/// <summary> /// 类型推断处理 /// </summary> public string GetTypeName(JsonType type, IJsonClassConfig config) { var arraysAsLists = !config.ExplicitDeserialization; switch (type.Type) { case JsonTypeEnum.Anything: return "object"; case JsonTypeEnum.Array: return arraysAsLists ? "IList<" + GetTypeName(type.InternalType, config) + ">" : GetTypeName(type.InternalType, config) + "[]"; case JsonTypeEnum.Dictionary: return "Dictionary<string, " + GetTypeName(type.InternalType, config) + ">"; case JsonTypeEnum.Boolean: return "bool"; case JsonTypeEnum.Float: return "double"; case JsonTypeEnum.Integer: return "int"; case JsonTypeEnum.Long: return "long"; case JsonTypeEnum.Date: return "DateTime"; case JsonTypeEnum.NonConstrained: return "object"; case JsonTypeEnum.NullableBoolean: return "bool?"; case JsonTypeEnum.NullableFloat: return "double?"; case JsonTypeEnum.NullableInteger: return "int?"; case JsonTypeEnum.NullableLong: return "long?"; case JsonTypeEnum.NullableDate: return "DateTime?"; case JsonTypeEnum.NullableSomething: return "object"; case JsonTypeEnum.Object: return type.AssignedName; case JsonTypeEnum.String: return "string"; default: throw new System.NotSupportedException("Unsupported json type"); } }
public void WriteClass(IJsonClassConfig config, TextWriter sw, JsonType type) { var visibility = config.InternalVisibility ? "internal" : "public"; if (config.UseNestedClasses) { if (!type.IsRoot) { if (ShouldApplyNoRenamingAttribute(config)) sw.WriteLine(" " + NoRenameAttribute); if (ShouldApplyNoPruneAttribute(config)) sw.WriteLine(" " + NoPruneAttribute); sw.WriteLine(" {0} class {1}", visibility, type.AssignedName); sw.WriteLine(" {"); } } else { if (ShouldApplyNoRenamingAttribute(config)) sw.WriteLine(" " + NoRenameAttribute); if (ShouldApplyNoPruneAttribute(config)) sw.WriteLine(" " + NoPruneAttribute); sw.WriteLine(" {0} class {1}", visibility, type.AssignedName); sw.WriteLine(" {"); } var prefix = config.UseNestedClasses && !type.IsRoot ? " " : " "; var shouldSuppressWarning = config.InternalVisibility && !config.UseProperties && !config.ExplicitDeserialization; if (shouldSuppressWarning) { sw.WriteLine("#pragma warning disable 0649"); if (!config.UsePascalCase) sw.WriteLine(); } if (type.IsRoot && config.ExplicitDeserialization) WriteStringConstructorExplicitDeserialization(config, sw, type, prefix); if (config.ExplicitDeserialization) { if (config.UseProperties) WriteClassWithPropertiesExplicitDeserialization(sw, type, prefix); else WriteClassWithFieldsExplicitDeserialization(sw, type, prefix); } else { WriteClassMembers(config, sw, type, prefix); } if (shouldSuppressWarning) { sw.WriteLine(); sw.WriteLine("#pragma warning restore 0649"); sw.WriteLine(); } if (config.UseNestedClasses && !type.IsRoot) sw.WriteLine(" }"); if (!config.UseNestedClasses) sw.WriteLine(" }"); sw.WriteLine(); }
public FieldInfo(IJsonClassConfig generator, string jsonMemberName, JsonType type, bool usePascalCase, IList<object> Examples) { this.generator = generator; this.JsonMemberName = jsonMemberName; this.MemberName = jsonMemberName; if (usePascalCase) MemberName = JsonClassGenerator.ToTitleCase(MemberName); this.Type = type; this.Examples = Examples; }
private void WriteStringConstructorExplicitDeserialization(IJsonClassConfig config, TextWriter sw, JsonType type, string prefix) { sw.WriteLine(); sw.WriteLine(prefix + "public {1}(string json)", config.InternalVisibility ? "internal" : "public", type.AssignedName); sw.WriteLine(prefix + " : this(JObject.Parse(json))"); sw.WriteLine(prefix + "{"); sw.WriteLine(prefix + "}"); sw.WriteLine(); }
private void WriteClassWithPropertiesExplicitDeserialization(TextWriter sw, JsonType type, string prefix) { sw.WriteLine(prefix + "private JObject __jobject;"); sw.WriteLine(prefix + "public {0}(JObject obj)", type.AssignedName); sw.WriteLine(prefix + "{"); sw.WriteLine(prefix + " this.__jobject = obj;"); sw.WriteLine(prefix + "}"); sw.WriteLine(); foreach (var field in type.Fields) { string variable = null; if (field.Type.MustCache) { variable = "_" + char.ToLower(field.MemberName[0]) + field.MemberName.Substring(1); sw.WriteLine(prefix + "[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]"); sw.WriteLine(prefix + "private {0} {1};", field.Type.GetTypeName(), variable); } sw.WriteLine(prefix + "public {0} {1}", field.Type.GetTypeName(), field.MemberName); sw.WriteLine(prefix + "{"); sw.WriteLine(prefix + " get"); sw.WriteLine(prefix + " {"); if (field.Type.MustCache) { sw.WriteLine(prefix + " if ({0} == null)", variable); sw.WriteLine(prefix + " {0} = {1};", variable, field.GetGenerationCode("__jobject")); sw.WriteLine(prefix + " return {0};", variable); } else { sw.WriteLine(prefix + " return {0};", field.GetGenerationCode("__jobject")); } sw.WriteLine(prefix + " }"); sw.WriteLine(prefix + "}"); sw.WriteLine(); } }
private void WriteClassWithFieldsExplicitDeserialization(TextWriter sw, JsonType type, string prefix) { sw.WriteLine(prefix + "public {0}(JObject obj)", type.AssignedName); sw.WriteLine(prefix + "{"); foreach (var field in type.Fields) { sw.WriteLine(prefix + " this.{0} = {1};", field.MemberName, field.GetGenerationCode("obj")); } sw.WriteLine(prefix + "}"); sw.WriteLine(); foreach (var field in type.Fields) { sw.WriteLine(prefix + "public readonly {0} {1};", field.Type.GetTypeName(), field.MemberName); } }
private void WriteClassMembers(IJsonClassConfig config, TextWriter sw, JsonType type, string prefix) { foreach (var field in type.Fields) { if (config.UsePascalCase || config.ExamplesInDocumentation) sw.WriteLine(); if (config.ExamplesInDocumentation) { sw.WriteLine(prefix + "/// <summary>"); sw.WriteLine(prefix + "/// Examples: " + field.GetExamplesText()); sw.WriteLine(prefix + "/// </summary>"); } if (config.UsePascalCase) { sw.WriteLine(prefix + "[JsonProperty(\"{0}\")]", field.JsonMemberName); } if (config.UseProperties) { sw.WriteLine(prefix + "public {0} {1} {{ get; set; }}", field.Type.GetTypeName(), field.MemberName); } else { sw.WriteLine(prefix + "public {0} {1};", field.Type.GetTypeName(), field.MemberName); } } }
private void GenerateClass(JObject[] examples, JsonType type) { var jsonFields = new Dictionary<string, JsonType>(); var fieldExamples = new Dictionary<string, IList<object>>(); var first = true; foreach (var obj in examples) { foreach (var prop in obj.Properties()) { JsonType fieldType; var currentType = new JsonType(this, prop.Value); var propName = prop.Name; if (jsonFields.TryGetValue(propName, out fieldType)) { var commonType = fieldType.GetCommonType(currentType); jsonFields[propName] = commonType; } else { var commonType = currentType; if (first) commonType = commonType.MaybeMakeNullable(this); else commonType = commonType.GetCommonType(JsonType.GetNull(this)); jsonFields.Add(propName, commonType); fieldExamples[propName] = new List<object>(); } var fe = fieldExamples[propName]; var val = prop.Value; if (val.Type == JTokenType.Null || val.Type == JTokenType.Undefined) { if (!fe.Contains(null)) { fe.Insert(0, null); } } else { var v = (val.Type == JTokenType.Array || val.Type == JTokenType.Object) ? val : val.Value<object>(); if (!fe.Any(x => v.Equals(x))) fe.Add(v); } } first = false; } if (UseNestedClasses) { foreach (var field in jsonFields) { Names.Add(field.Key.ToLower()); } } foreach (var field in jsonFields) { var fieldType = field.Value; if (fieldType.Type == JsonTypeEnum.Object) { var subexamples = new List<JObject>(examples.Length); foreach (var obj in examples) { JToken value; if (obj.TryGetValue(field.Key, out value)) { if (value.Type == JTokenType.Object) { subexamples.Add((JObject)value); } } } fieldType.AssignName(CreateUniqueClassName(field.Key)); GenerateClass(subexamples.ToArray(), fieldType); } if (fieldType.InternalType != null && fieldType.InternalType.Type == JsonTypeEnum.Object) { var subexamples = new List<JObject>(examples.Length); foreach (var obj in examples) { JToken value; if (obj.TryGetValue(field.Key, out value)) { if (value.Type == JTokenType.Array) { foreach (var item in (JArray)value) { if (!(item is JObject)) throw new NotSupportedException("Arrays of non-objects are not supported yet."); subexamples.Add((JObject)item); } } else if (value.Type == JTokenType.Object) { foreach (var item in (JObject)value) { if (!(item.Value is JObject)) throw new NotSupportedException("Arrays of non-objects are not supported yet."); subexamples.Add((JObject)item.Value); } } } } field.Value.InternalType.AssignName(CreateUniqueClassNameFromPlural(field.Key)); GenerateClass(subexamples.ToArray(), field.Value.InternalType); } } type.Fields = jsonFields .Select(x => new FieldInfo(this, x.Key, x.Value, UsePascalCase, fieldExamples[x.Key])) .ToArray(); Types.Add(type); }
public void GenerateClasses() { if (CodeWriter == null) CodeWriter = new CSharpCodeWriter(); if (ExplicitDeserialization && !(CodeWriter is CSharpCodeWriter)) throw new ArgumentException("Explicit deserialization is obsolete and is only supported by the C# provider."); if (used) throw new InvalidOperationException("This instance of JsonClassGenerator has already been used. Please create a new instance."); used = true; var writeToDisk = TargetFolder != null; if (writeToDisk && !Directory.Exists(TargetFolder)) Directory.CreateDirectory(TargetFolder); JObject[] examples; var example = Example.StartsWith("HTTP/") ? Example.Substring(Example.IndexOf("\r\n\r\n")) : Example; using (var sr = new StringReader(example)) using (var reader = new JsonTextReader(sr)) { var json = JToken.ReadFrom(reader); if (json is JArray) { examples = ((JArray)json).Cast<JObject>().ToArray(); } else if (json is JObject) { examples = new[] { (JObject)json }; } else { throw new Exception("Sample JSON must be either a JSON array, or a JSON object."); } } Types = new List<JsonType>(); Names.Add(MainClass); var rootType = new JsonType(this, examples[0]); rootType.IsRoot = true; rootType.AssignName(MainClass); GenerateClass(examples, rootType); //if (writeToDisk) //{ // var parentFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); // if (writeToDisk && !NoHelperClass && ExplicitDeserialization) // File.WriteAllBytes(Path.Combine(TargetFolder, "JsonClassHelper.cs"), Properties.Resources.JsonClassHelper); // if (SingleFile) // { // WriteClassesToFile(Path.Combine(TargetFolder, MainClass + CodeWriter.FileExtension), Types); // } // else // { // foreach (var type in Types) // { // var folder = TargetFolder; // if (!UseNestedClasses && !type.IsRoot && SecondaryNamespace != null) // { // var s = SecondaryNamespace; // if (s.StartsWith(Namespace + ".")) s = s.Substring(Namespace.Length + 1); // folder = Path.Combine(folder, s); // Directory.CreateDirectory(folder); // } // WriteClassesToFile(Path.Combine(folder, (UseNestedClasses && !type.IsRoot ? MainClass + "." : string.Empty) + type.AssignedName + CodeWriter.FileExtension), new[] { type }); // } // } //} //else if (OutputStream != null) { WriteClassesToFile(OutputStream, Types); } }
public static JsonType GetCommonType(IJsonClassConfig generator, JToken[] tokens) { if (tokens.Length == 0) return new JsonType(generator, JsonTypeEnum.NonConstrained); var common = new JsonType(generator, tokens[0]).MaybeMakeNullable(generator); for (int i = 1; i < tokens.Length; i++) { var current = new JsonType(generator, tokens[i]); common = common.GetCommonType(current); } return common; }
public JsonType GetCommonType(JsonType type2) { var commonType = GetCommonTypeEnum(this.Type, type2.Type); if (commonType == JsonTypeEnum.Array) { if (type2.Type == JsonTypeEnum.NullableSomething) return this; if (this.Type == JsonTypeEnum.NullableSomething) return type2; var commonInternalType = InternalType.GetCommonType(type2.InternalType).MaybeMakeNullable(generator); if (commonInternalType != InternalType) return new JsonType(generator, JsonTypeEnum.Array) { InternalType = commonInternalType }; } //if (commonType == JsonTypeEnum.Dictionary) //{ // var commonInternalType = InternalType.GetCommonType(type2.InternalType); // if (commonInternalType != InternalType) return new JsonType(JsonTypeEnum.Dictionary) { InternalType = commonInternalType }; //} if (this.Type == commonType) return this; return new JsonType(generator, commonType).MaybeMakeNullable(generator); }