Reputation: 1060
I am trying to update the name of a property in a Json serializable class that is already released, so I need to make it backwards compatible.
public class myClass
{
//[JsonIgnore] - now old json files can't be read, so this won't work...
//[JsonProperty(ReferenceLoopHandling = ReferenceLoopHandling.Error)] - didn't do anything
//[JsonProperty(nameof(NewName)] - throws error - "That already exists"
[Obselete("Use NewName instead")]
public List<string> OldName { get => newName; set => newName = value; }
public List<string> NewName { get; set; } = new List<string>();
}
And I use it like this:
[Test]
public void test()
{
var foo = new myClass()
{
OldName = { "test" },
};
var bar = JsonConvert.SerializeObject(foo);
var result = JsonConvert.DeserializeObject(bar, typeof(myClass));
}
When I look at the value in result.NewName, I find this list: {"test", "test"}
, but I expected this list: {"test"}
The desired behavior:
How would you accomplish this?
Upvotes: 1
Views: 915
Reputation: 1060
This answer was very helpful. Basically you refactor your code like this:
public class ControlReportResult : TargetReportResult
{
public List<string> NewName { get; set; } = new();
[JsonIgnore] // this stops the serializer from paying attention to this property
[Obsolete("Use NewName instead")]
public List<string> OldName => { get => NewName; set => NewName = value; }
[JsonProperty("OldName")] //This doesn't throw an error because the serializer was told to ignore the real OldName property
private List<string> _jsonOldNameSetter { set => NewName = value; } // no getter, so we are never going to write OldName out.
}
Some notes:
It shouldn't happen, but if you still somehow end up with a json file with both an OldName and a NewName, add the attribute [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
above OldName and NewName - this way they will overwrite each other, rather than appending.
Upvotes: 0
Reputation: 43969
Try this
var foo = "{\"OldName\":[\"old test\"]}";
var fooN = "{\"NewName\":[\"new test\"]}";
var result = JsonConvert.DeserializeObject(foo, typeof(myClass));
//or
var result = JsonConvert.DeserializeObject(fooN, typeof(myClass));
var json = JsonConvert.SerializeObject(result);
json result:
{"NewName":["new test"]}
//or
{"NewName":["old test"]}
class
public class myClass
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<string> OldName {
get {return null; }
set {NewName=value;}
}
public List<string> NewName {get; set;}
}
Upvotes: 1
Reputation: 856
This works using System.Text.Json.
var foo = new myClass()
{
OldName = { "test" },
};
var bar = JsonSerializer.Serialize<myClass>(foo);
var result = JsonSerializer.Deserialize<myClass>(bar);
Upvotes: 0