JSON.Net Deserialize or Serialize JSON String and Map Properties to Different Property Names Defined at Runtime

Json.NET deserialize or serialize json string and map properties to different property names defined at runtime

You could use a custom ContractResolver to do this. Basically it is the same idea as putting a [JsonProperty] attribute on each class member for which you want to map to a different JSON property name, except you do it programmatically via the resolver. You can pass a dictionary of your desired mappings to the resolver when setting it up just before deserializing.

Here is what the custom resolver code might look like:

class DynamicMappingResolver : DefaultContractResolver
{
private Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap;

public DynamicMappingResolver(Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap)
{
this.memberNameToJsonNameMap = memberNameToJsonNameMap;
}

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty prop = base.CreateProperty(member, memberSerialization);
Dictionary<string, string> dict;
string jsonName;
if (memberNameToJsonNameMap.TryGetValue(member.DeclaringType, out dict) &&
dict.TryGetValue(member.Name, out jsonName))
{
prop.PropertyName = jsonName;
}
return prop;
}
}

To use the resolver, first construct a Dictionary<Type, Dictionary<string, string>> containing your mappings. The outer dictionary's key is the the class type(s) whose properties you want to map; the inner dictionary is a mapping of the class property names to JSON property names. You only need to provide a mapping for the properties whose names don't already match the JSON.

So, for example, if your JSON looked like this (notice the changed names of the properties inside the details object)...

{
"values": {
"details": {
"foo": "94",
"bar": "47",
"baz": "32",
"quux": 1
},
count: 4
}
}

...and you wanted to map it to the classes in your question, you would create the dictionary like this:

var map = new Dictionary<Type, Dictionary<string, string>>
{
{
typeof(Details),
new Dictionary<string, string>
{
{"property1", "foo"},
{"property2", "bar"},
{"property3", "baz"},
{"property4", "quux"}
}
}
};

The last step is to set up the serializer settings with a new resolver instance, giving it the mapping dictionary you just constructed, and then pass the settings to JsonConvert.DeserializeObject().

var settings = new JsonSerializerSettings
{
ContractResolver = new DynamicMappingResolver(map)
};

var root = JsonConvert.DeserializeObject<RootObject>(json, settings);

Here is a demo: https://dotnetfiddle.net/ULkB0J

.NET NewtonSoft JSON deserialize map to a different property name

Json.NET - Newtonsoft has a JsonPropertyAttribute which allows you to specify the name of a JSON property, so your code should be:

public class TeamScore
{
[JsonProperty("eighty_min_score")]
public string EightyMinScore { get; set; }
[JsonProperty("home_or_away")]
public string HomeOrAway { get; set; }
[JsonProperty("score ")]
public string Score { get; set; }
[JsonProperty("team_id")]
public string TeamId { get; set; }
}

public class Team
{
public string v1 { get; set; }
[JsonProperty("attributes")]
public TeamScore TeamScores { get; set; }
}

public class RootObject
{
public List<Team> Team { get; set; }
}

Documentation: Serialization Attributes

Mapping multiple property names to the same field in Newtonsoft.JSON

You could use a custom ContractResolver in this answer:

Json.NET deserialize or serialize json string and map properties to different property names defined at runtime

Or

Use [JsonProperty("")] to look for different variations of the property name and return with one of the properties like this:

public class Message
{
private string _name;

[JsonProperty("Navn" )]
public string NorwegianName { get; set; }

[JsonProperty("Name")]
public string Name {
get { return _name ?? NorwegianName; }
set { _name = value; } }
}

This will return the name with JSON property name: Navn or Name.

Change json property name in output using Json.Net

You could use custom resolve to create desired behaviour:

public class CustomContractResolver : DefaultContractResolver
{
public bool UseJsonPropertyName { get; }

public CustomContractResolver(bool useJsonPropertyName)
{
UseJsonPropertyName = useJsonPropertyName;
}

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (!UseJsonPropertyName)
property.PropertyName = property.UnderlyingName;

return property;
}
}

public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}

var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
var serializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CustomContractResolver(false)
};
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(true)
};

var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
var jsonNew = JsonConvert.SerializeObject(obj, serializerSettings);

Kudos to NtFreX and his answer. I'm providing mine so that you can indicate that your question is resolved.

Deserializing JSON when inner property names vary

Newtonsoft didn't seem to have any problem with it..

    public partial class Blah
{
[JsonProperty("currencies")]
public Dictionary<string, Currency> Currencies { get; set; }
}

public partial class Currency
{
[JsonProperty("name")]
public string Name { get; set; }

[JsonProperty("symbol")]
public string Symbol { get; set; }
}

And

var blah = JsonConvert.DeserializeObject<Blah[]>(jsonString);

Sample Image

..though it's probably worth noting I think you have your parent and outer the wrong way round if this json is just a fragment..

Sample Image

Newtonsoft json - deserialize classes with same name, but different properties

"answers" here is a property name, not a class name, so all you need to do is define your classes in a way that matches the pattern you've shown. Having two different properties named "answers" doesn't present any particular complication.

class Response
{
public IList<OuterAnswer> answers { get; set; }
}

class OuterAnswer
{
public Tag tag { get; set; }
public bool option { get; set; }
public IList<InnerAnswer> answers { get; set; }
public string question { get; set; }
public long seller_question_id { get; set; }
}

class InnerAnswer
{
public string label { get; set; }
public string value { get; set; }
public bool show_inline { get; set; }
}


Related Topics



Leave a reply



Submit