public static void Ignore(this JsonMapBase jsonMap, LambdaExpression expr) { var memberInfo = GetMemberInfoFromExpression(expr); jsonMap.Actions.Add( (member, property, mode) => { if (jsonMap.AcceptsMember(member, memberInfo)) { property.ShouldSerialize = instance => false; } }); }
public static void Map(this JsonMapBase jsonMap, LambdaExpression expr, string name) { var memberInfo = GetMemberInfoFromExpression(expr); jsonMap.Actions.Add( (member, property, mode) => { if (TypeExtraInfo.MembersAreTheSame(member, memberInfo)) { property.PropertyName = name; property.ShouldSerialize = instance => true; } }); }
public static void Map(this JsonMapBase jsonMap, LambdaExpression expr, string name) { var memberInfo = GetMemberInfoFromExpression(expr); jsonMap.Actions.Add( (member, property, mode) => { if (member.MetadataToken == memberInfo.MetadataToken && member.DeclaringType == memberInfo.DeclaringType) { property.PropertyName = name; property.ShouldSerialize = instance => true; } }); }
public JsonMapsTreeNode(JsonMapBase mapper, Type parent, Type[] children) { this.Mapper = mapper; this.Parent = parent; this.Children = new ReadOnlyCollection <Type>(children); }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // the question here is: is this objectType associated with any class hierarchy in the `JsonMap` list? var cachedData = this.GetInfoFromTypeCached(objectType); while (this.blockOnce == 1) { throw new Exception("Writing is blocked but should not."); } if (reader.TokenType == JsonToken.Null) { var isNullable = Nullable.GetUnderlyingType(objectType) != null || !objectType.GetTypeInfo().IsValueType; if (isNullable) { return(null); } } var jo = JObject.Load(reader); var value = reader.Value; // Looking for discriminators: // - match the discriminators of the type given by `objectType` // - match the discriminators of subtypes of `objectType` // STEP 1: match the discriminators of the type given by `objectType` string discriminatorFieldValue = null; bool foundBaseIAndSubtypes = false; JsonMapBase classMapToUse = null; foreach (var jsonMapBase in cachedData.Mappers.Reverse()) { if (foundBaseIAndSubtypes) { throw new Exception($"IAndSubtypes mapper does not accept child mappers."); } if (jsonMapBase is IAndSubtypes) { if (jsonMapBase.DiscriminatorFieldName != null) { var discriminatorFieldValueToken = jo[jsonMapBase.DiscriminatorFieldName]; if (discriminatorFieldValueToken?.Type == JTokenType.String) { discriminatorFieldValue = discriminatorFieldValueToken.Value <string>(); } } foundBaseIAndSubtypes = true; var jsonMapWithSubtypes = jsonMapBase as IAndSubtypes; value = jsonMapWithSubtypes.CreateObject(discriminatorFieldValue); serializer.Populate(jo.CreateReader(), value); discriminatorFieldValue = null; } else { var jsonSubclassMap = jsonMapBase as JsonSubclassMap; if (jsonSubclassMap?.DiscriminatorFieldValue != null && discriminatorFieldValue != null) { if (jsonSubclassMap.DiscriminatorFieldValue != discriminatorFieldValue) { throw new Exception($"Discriminator does not match."); } discriminatorFieldValue = null; } if (jsonMapBase.DiscriminatorFieldName != null) { var discriminatorFieldValueToken = jo[jsonMapBase.DiscriminatorFieldName]; if (discriminatorFieldValueToken?.Type == JTokenType.String) { discriminatorFieldValue = discriminatorFieldValueToken.Value <string>(); } } classMapToUse = jsonMapBase; } } // STEP 2: match the discriminators of subtypes of `objectType` JsonMapBase subclassMapToUse = null; foreach (var jsonSubmappers in cachedData.SubMappers) { string subDiscriminatorFieldValue = discriminatorFieldValue; bool foundSubIAndSubtypes = foundBaseIAndSubtypes; JsonMapBase subclassMapToUse2 = null; foreach (var submapper in jsonSubmappers.Reverse()) { if (foundSubIAndSubtypes) { throw new Exception($"IAndSubtypes mapper does not accept child mappers."); } if (submapper is IAndSubtypes) { if (submapper.DiscriminatorFieldName != null) { var discriminatorFieldValueToken = jo[submapper.DiscriminatorFieldName]; if (discriminatorFieldValueToken?.Type == JTokenType.String) { subDiscriminatorFieldValue = discriminatorFieldValueToken.Value <string>(); } if (subDiscriminatorFieldValue == null) { throw new Exception($"Discriminator field not found."); } } foundSubIAndSubtypes = true; var jsonMapWithSubtypes = submapper as IAndSubtypes; value = jsonMapWithSubtypes.CreateObject(subDiscriminatorFieldValue); serializer.Populate(jo.CreateReader(), value); subDiscriminatorFieldValue = null; } else { var jsonSubclassMap = submapper as JsonSubclassMap; if (jsonSubclassMap != null) { if (jsonSubclassMap.DiscriminatorFieldValue != null) { if (jsonSubclassMap.DiscriminatorFieldValue != subDiscriminatorFieldValue) { break; } if (subclassMapToUse != null) { throw new Exception($"Ambiguous maps for the type `{submapper.SerializedType.Name}`"); } subDiscriminatorFieldValue = null; subclassMapToUse2 = jsonSubclassMap; } } else { if (cachedData.Mappers.Length > 0) { throw new Exception($"Sub mappers must be subclasses of `{typeof(JsonSubclassMap).Name}`: `{cachedData.Mappers[0].GetType().Name}`"); } if (subclassMapToUse != null) { throw new Exception($"Ambiguous maps for the type `{submapper.SerializedType.Name}`"); } subclassMapToUse2 = submapper; } if (submapper.DiscriminatorFieldName != null) { var discriminatorFieldValueToken = jo[submapper.DiscriminatorFieldName]; if (discriminatorFieldValueToken?.Type == JTokenType.String) { subDiscriminatorFieldValue = discriminatorFieldValueToken.Value <string>(); } if (subDiscriminatorFieldValue == null) { break; } } } } if (subclassMapToUse2 != null) { subclassMapToUse = subclassMapToUse2; } if (subclassMapToUse2 != null && subDiscriminatorFieldValue != null) { throw new Exception("Value of discriminator field not verified by any subclass map."); } } if (subclassMapToUse == null && discriminatorFieldValue != null) { throw new Exception("Value of discriminator field not verified by any subclass map."); } // STEP 3: Creating the new value with the correct JsonMapBase class if any // - by the way, there is no JsonMapBase when a IAndSubtypes mapper is found var classMapToUse2 = subclassMapToUse ?? classMapToUse; if (classMapToUse2 != null) { if (!classMapToUse2.CanCreateNew()) { throw new Exception($"Cannot create object of type `{classMapToUse2.SerializedType}`"); } value = classMapToUse2.CreateNew(); serializer.Populate(jo.CreateReader(), value); } return(value); }