Reputation: 251
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!
Upvotes: 14
Views: 10018
Reputation: 21
Maybe I'm late to the party, but this also works:
[JsonPropertyName("pname")]
public string? PName { private get; set; }
public string? Name => PName;
Upvotes: 2
Reputation: 48154
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);
Upvotes: 7
Reputation: 56586
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.
Upvotes: 0