private bool CanMerge(JsonRoot other, out JsonRoot mergedType) { mergedType = null; if (this.ArrayRank != other.ArrayRank) { return(false); } if (this.IsUserDefinedType != other.IsUserDefinedType) { return(false); } if (this.CanMergeInto(other, out mergedType)) { return(true); } if (other.CanMergeInto(this, out mergedType)) { return(true); } return(false); }
private void AddMembers(CodeNamespace ns, CodeTypeDeclaration typeDecl, JsonRoot jsonRoot, List <string> existingTypes) { foreach (var memberName in jsonRoot.Members.Keys) { string fieldName = EscapeFieldName(memberName); var member = jsonRoot.Members[memberName]; CodeTypeReference fieldType; if (member.IsUserDefinedType) { string fieldTypeName = this.GenerateType(ns, member, existingTypes); fieldType = new CodeTypeReference(fieldTypeName); } else { fieldType = new CodeTypeReference(member.ElementType ?? typeof(object)); } for (int i = 0; i < member.ArrayRank; i++) { fieldType = new CodeTypeReference(fieldType, 1); } // TODO: implement members as properties instead of fields CodeMemberField field = new CodeMemberField(fieldType, fieldName); field.Attributes = MemberAttributes.Public; typeDecl.Members.Add(field); this.AddMemberAttributeDeclaration(field, memberName); } }
private static JsonRoot ParseJArrayIntoDataContract(JArray root, string rootTypeName) { if (root.Count == 0) { return(new JsonRoot(null, 1)); } JsonRoot first = ParseJsonIntoDataContract(root[0], rootTypeName); for (int i = 1; i < root.Count; i++) { JsonRoot next = ParseJsonIntoDataContract(root[i], rootTypeName); JsonRoot mergedType; if (first.CanMerge(next, out mergedType)) { first = mergedType; } else { throw new ArgumentException(string.Format("Cannot merge array elements {0} ({1}) and {2} ({3})", 0, root[0], i, root[i])); } } if (first.IsUserDefinedType) { return(new JsonRoot(first.UserDefinedTypeName, first.ArrayRank + 1, first.Members)); } else { return(new JsonRoot(first.ElementType, first.ArrayRank + 1)); } }
private bool CanMergeInto(JsonRoot other, out JsonRoot mergedType) { if (this.IsUserDefinedType) { return(this.CanMergeIntoUserDefinedType(other, out mergedType)); } else { return(this.CanMergeIntoPrimitiveType(other, out mergedType)); } }
public void GenerateCode(JsonRoot root, TextWriter writer) { CodeCompileUnit result = new CodeCompileUnit(); result.Namespaces.Add(new CodeNamespace()); GenerateType(result.Namespaces[0], root, new List <string>()); CodeDomProvider provider = CodeDomProvider.CreateProvider(this.language); CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BracingStyle = "C"; provider.GenerateCodeFromCompileUnit(result, writer, options); }
public static JsonRoot ParseJsonIntoDataContract(JToken root, string rootTypeName) { JsonRoot results = null; if (root == null || root.Type == JTokenType.Null) { results = new JsonRoot(null, 0); } else { switch (root.Type) { case JTokenType.Boolean: results = new JsonRoot(typeof(bool), 0); break; case JTokenType.String: results = new JsonRoot(typeof(string), 0); break; case JTokenType.Float: results = new JsonRoot(typeof(double), 0); break; case JTokenType.Date: results = new JsonRoot(typeof(DateTime), 0); break; case JTokenType.TimeSpan: results = new JsonRoot(typeof(TimeSpan), 0); break; case JTokenType.Integer: results = new JsonRoot(GetClrIntegerType(root.ToString()), 0); break; case JTokenType.Object: results = ParseJObjectIntoDataContract((JObject)root, rootTypeName); break; case JTokenType.Array: results = ParseJArrayIntoDataContract((JArray)root, rootTypeName); break; default: throw new ArgumentException("Cannot work with JSON token of type " + root.Type); } } return(results); }
private bool CanMergeIntoUserDefinedType(JsonRoot other, out JsonRoot mergedType) { bool sameAsThis = true; mergedType = null; Dictionary <string, JsonRoot> members = new Dictionary <string, JsonRoot>(); foreach (var memberName in this.Members.Keys.Union(other.Members.Keys)) { if (this.Members.ContainsKey(memberName) && other.Members.ContainsKey(memberName)) { JsonRoot member1 = this.Members[memberName]; JsonRoot member2 = other.Members[memberName]; JsonRoot merged; if (!member1.CanMerge(member2, out merged)) { return(false); } else { if (merged != member1) { sameAsThis = false; } members.Add(memberName, merged); } } else if (this.Members.ContainsKey(memberName)) { members.Add(memberName, this.Members[memberName]); } else { sameAsThis = false; members.Add(memberName, other.Members[memberName]); } } if (sameAsThis) { mergedType = this; } else { mergedType = new JsonRoot(this.UserDefinedTypeName, this.ArrayRank, members); } return(true); }
public List <string> GetAncestors() { List <string> result = new List <string>(); JsonRoot temp = this; while (temp != null) { if (temp.Parent != null) { result.Insert(0, temp.UserDefinedTypeName); } temp = temp.Parent; } result.Insert(0, "<<root>>"); return(result); }
private static JsonRoot ParseJObjectIntoDataContract(JObject root, string rootTypeName) { Dictionary <string, JsonRoot> fields = new Dictionary <string, JsonRoot>(); foreach (JProperty property in root.Properties()) { JsonRoot fieldType = ParseJsonIntoDataContract(property.Value, property.Name); fields.Add(property.Name, fieldType); } JsonRoot result = new JsonRoot(rootTypeName, 0, fields); foreach (var field in fields.Values) { field.Parent = result; } return(result); }
private string GenerateType(CodeNamespace ns, JsonRoot root, List <string> existingTypes) { if (!root.IsUserDefinedType) { return(null); } CodeTypeDeclaration rootType = new CodeTypeDeclaration(GetUniqueDataContractName(root.UserDefinedTypeName, existingTypes)); existingTypes.Add(rootType.Name); rootType.Attributes = MemberAttributes.Public; rootType.IsPartial = true; rootType.IsClass = true; ns.Types.Add(rootType); rootType.Comments.Add( new CodeCommentStatement( string.Format( "Type created for JSON at {0}", string.Join(" --> ", root.GetAncestors())))); AddAttributeDeclaration(rootType, rootType.Name, root.UserDefinedTypeName); AddMembers(ns, rootType, root, existingTypes); return(rootType.Name); }
private bool CanMergeIntoPrimitiveType(JsonRoot other, out JsonRoot mergedType) { if (this.ElementType == other.ElementType) { mergedType = this; return(true); } bool isThisNullable = this.IsNullableType(); bool isOtherNullable = other.IsNullableType(); Type thisElementType = this.ElementType != null && this.ElementType.IsGenericType && this.ElementType.GetGenericTypeDefinition() == typeof(Nullable <>) ? this.ElementType.GetGenericArguments()[0] : this.ElementType; Type otherElementType = other.ElementType != null && other.ElementType.IsGenericType && other.ElementType.GetGenericTypeDefinition() == typeof(Nullable <>) ? other.ElementType.GetGenericArguments()[0] : other.ElementType; if (thisElementType == otherElementType) { // one nullable, the other not if (isThisNullable) { mergedType = this; } else { mergedType = other; } return(true); } if (thisElementType == null) { if (isOtherNullable || otherElementType == typeof(string)) { mergedType = other; return(true); } mergedType = new JsonRoot(typeof(Nullable <>).MakeGenericType(otherElementType), this.ArrayRank); return(true); } if (otherElementType == null) { if (isThisNullable || thisElementType == typeof(string)) { mergedType = this; return(true); } mergedType = new JsonRoot(typeof(Nullable <>).MakeGenericType(thisElementType), this.ArrayRank); return(true); } // Number coercions if (this.ElementType == typeof(int)) { if (other.ElementType == typeof(long) || other.ElementType == typeof(double)) { mergedType = other; if (!mergedType.IsNullableType() && isThisNullable) { mergedType = new JsonRoot(typeof(Nullable <>).MakeGenericType(mergedType.ElementType), mergedType.ArrayRank); } return(true); } } else if (this.ElementType == typeof(long)) { if (other.ElementType == typeof(double)) { mergedType = other; if (!mergedType.IsNullableType() && isThisNullable) { mergedType = new JsonRoot(typeof(Nullable <>).MakeGenericType(mergedType.ElementType), mergedType.ArrayRank); } return(true); } } mergedType = null; return(false); }