问题
I'm deserializing some JSON from a server which is, for the most part, simple:
{
"id": "ABC123"
"number" 1234,
"configured_perspective": "ComplexPerspective[WithOptions,Encoded]"
}
That "configured_perspective" property, however, is an unfortunate case of the server using a weirdly put-together string when a nested object would have been better.
To ease the suffering of our .NET users, I convert this into a custom class in my object model:
public class Example
{
public string id { get; set; }
public int number { get; set; }
public Perspective configured_perspective { get; set; }
}
// Note, instances of this class are immutable
public class Perspective
{
public CoreEnum base_perspective { get; }
public IEnumerable<OptionEnum> options { get; }
public Perspective(CoreEnum baseArg, IEnumerable<OptionEnum> options) { ... }
public Perspective(string stringRepresentation) {
//Parses that gross string to this nice class
}
public static implicit operator Perspective(string fromString) =>
new Perspective(fromString);
public override string ToString() =>
base_perspective + '[' + String.Join(",", options) + ']';
}
As you can see, I've put together a custom class Perspective
that converts to and from the JSON string, but I can't seem to get Newtonsoft JSON to automatically convert the string to my Perspective class.
I tried getting it to call the string constructor with the [JsonConstructor]
attribute, but it just calls the constructor with null
, not with the string value present in the JSON.
I was under the impression (based on https://stackoverflow.com/a/34186322/529618) that JSON.NET would use implicit/explicit string conversion operators to convert a simple string in JSON to an instance of the target type when available, but it seems to ignore it, and just returns the error:
Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Perspective. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'configured_perspective'
I'm trying to avoid resorting to writing a custom JsonConverter for my Example
class - I was pretty sure there would be an out-of-the-box way to convert simple string values to a non-string property type, I just haven't found it yet.
回答1:
I actually wrote out a custom serializer class before doing reading the last of your article, but I then had an idea.
What if we modified example to not serialize it to Perspective? And we were somewhat lazy about it?
public class Example
{
public string id { get; set; }
public int number { get; set; }
public string configured_perspective { get; set; }
private Perspective _configuredPespective;
[JsonIgnore]
public Perspective ConfiguredPerspective => _configuredPerspective == null ? new Perspective(configured_persective) : _configuredPerspective;
}
It's not perfect, and we hold onto the string wasting memory, but it might work for you as a work-around.
回答2:
Currently I'm using the following variation on @Jlalonde's suggestion - tweaked such that the user experience doesn't change, taking advantage of the fact that JSON.NET looks for private properties as well.
public class Example
{
public string id { get; set; }
public int number { get; set; }
[JsonIgnore]
public Perspective configured_perspective { get; set; }
[DataMember(Name = "configured_perspective")]
private string configured_perspective_serialized
{
get => configured_perspective?.ToString();
set => configured_perspective = value == null ? null : new Perspective(value);
}
}
来源:https://stackoverflow.com/questions/54829291/deserializing-a-string-property-value-to-a-class-instance-using-json-net