1

I am trying to read a JSON file, rename the property names, and export a new JSON with the new names. As stated in this example, https://www.newtonsoft.com/json/help/html/JsonPropertyName.htm, we can use JsonProperty to specify a different name internally in the code. However, when you export the json, it returns the original name. So in the example it still returned "release_date" instead of "ReleaseDate" when it was logged in the console. Is there any way to do this without creating a brand new object?

To clear things up, here is example of what I am trying to do:

JSON Input:

{ "name": "Starcraft", "release_date": "1998-01-01T00:00:00" }

Object Used to deserialize the data:

public class Videogame
{
    public string name{ get; set; }

    [JsonProperty("release_date")]
    public DateTime releaseDate { get; set; }
}

Code that is called:

var json = JsonConvert.DeserializeObject<Videogame>(File.ReadAllText(path))
Console.WriteLine(JsonConvert.SerializeObject(json));

Resulted Output:

{ "name": "Starcraft", "release_date": "1998-01-01T00:00:00" }

Desired Output:

{ "name": "Starcraft", "releaseDate": "1998-01-01T00:00:00" }

The only way that I currently know how to solve it is to create a new object and use it to serialize my output. Wasn't sure if there is any simpler way to do this.

Marin Petkov
  • 2,128
  • 4
  • 17
  • 23
  • As seen in the example, Console.WriteLine(json); showed up as "release_date" not as "ReleaseDate". What am I missing here? Same thing happens when I return the json via an endpoint. – Marin Petkov Jan 19 '18 at 19:50
  • 1
    @dbc - Added more info to the question. – Marin Petkov Jan 19 '18 at 20:02
  • In Jackson there is https://fasterxml.github.io/jackson-annotations/javadoc/2.6/index.html?com/fasterxml/jackson/annotation/JsonProperty.Access.html – Thomas Weller Jan 19 '18 at 20:04
  • 2
    Have you taken a look at this? Looks pretty similar to what you need: https://stackoverflow.com/questions/44632448/use-different-name-for-serializing-and-deserializing-with-json-net – Vlad Stryapko Jan 19 '18 at 20:11
  • @VladStryapko - JsonSerializerSettings is exactly what I was looking for! Can you post it as an answer so that I can accept it? – Marin Petkov Jan 19 '18 at 20:17
  • 1
    If your name mapping is deterministic (camel case to snake case) you can use a custom naming strategy in `JsonSerializerSettings` as shown in @VladStryapko's linked answer [Use different name for serializing and deserializing with Json.Net](https://stackoverflow.com/q/44632448/3744182). If the name mapping is not deterministic, consider using `ConditionalNameContractResolver` from [JsonProperty WebApi request and response models](https://stackoverflow.com/q/34362628/3744182). – dbc Jan 19 '18 at 20:18
  • @MarinPetkov I'm not really sure if it's OK since your question is kind of duplicate in that sense; I've provided an answer nonetheless, so you can mark it as accepted if it solves your issue. – Vlad Stryapko Jan 19 '18 at 20:23

2 Answers2

3

The following will work:

public class Videogame
{
    public string name{ get; set; }

    [JsonProperty("release_date")]
    public DateTime old 
    { 
          set { ReleaseDate = value; }
    }

    [JsonProperty("releaseDate")]
    public DateTime ReleaseDate { get; set; }
}

When deserializing, the old property will redirect its value to the new property.

Since the old property is a setter only, it will not be serialized back.

I would not consider this approach for large amounts of renaming. It's then better to follow the advices given in the comments.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
2

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.

Vlad Stryapko
  • 1,035
  • 11
  • 29