JsonProperty - Use different name for deserialization, but use original name for serialization?

拟墨画扇 提交于 2019-12-17 19:47:12

问题


I am retrieving JSON from an API. I am using newtonsoft (this is json.net right?) to deserialize this into a list of objects. It works.

Unfortunately I also need to pass this along to someone else as JSON (they can't call the API directly only I have access to it). I say unfortunately because I need to OUTPUT my JSON that is different from what is being received (the property names need to be different).

For example, I have a class called Person, with a property called Name. I want to get "People", so I make my request to that API to get JSON as above, and get back a list of Person. Unfortunately the API doesn't return me people with Name properties, it returns me pname. So to map this, I just do:

 [JsonProperty("pname")]

This is all well and good - it converts pname to name and my class now has the value! I have a list of people with names.

Now I need to give this list of objects BACK to someone else as "Name", However when I serialize my people class back to JSON, it writes out the JSON as "pname" when I really want to write it out as "Name". I suspect it's picking up the "JsonProperty".

Is there a way to just have it use pname for deserialization, but use the original property value for serialization?

Thanks!


回答1:


You can create a custom contract resolver that sets the property names back to the ones you've defined in the C# class before serilization. Below is some example code;

class OriginalNameContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        // Let the base class create all the JsonProperties 
        IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);

        // assign the C# property name
        foreach (JsonProperty prop in list)
        {
            prop.PropertyName = prop.UnderlyingName;
        }

        return list;
    }
}

Use it like this;

    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.Formatting = Formatting.Indented;
    if (useLongNames)
    {
        settings.ContractResolver = new OriginalNameContractResolver();
    }

    string response = JsonConvert.SerializeObject(obj, settings);



回答2:


You might be able to write a custom JsonConverter to do it with just one Person class, but I'd recommend having separate classes, since the data is modeled differently in the two places. Even if you don't plan to right now, you might find yourself needing to deserialize from Name or serialize to pname at some point. This also allows your classes to differ more substantially. You could use AutoMapper (or similar) to easily convert between the two. E.g.

public class PersonFromThatApi
{
    [JsonProperty("pname")]
    public string Name { get; set; }
}
public class Person
{
    public string Name { get; set; }
}

Mapper.CreateMap<PersonFromThatApi, Person>();
Mapper.CreateMap<Person, PersonFromThatApi>();

var person1 = JsonConvert.DeserializeObject<PersonFromThatApi>(
                               @"{""pname"":""George""}");
Person person2 = Mapper.Map<Person>(person1);
string s = JsonConvert.SerializeObject(person2); // {"Name":"George"}

And yes, Newtonsoft.Json is the namespace of Json.NET. Don't ask me why they chose totally different names for those two things.



来源:https://stackoverflow.com/questions/22993576/jsonproperty-use-different-name-for-deserialization-but-use-original-name-for

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!