使用JSON.Net将字符串属性值反序列化为类实例

时间:2019-02-22 14:30:31

标签: c# json json.net deserialization implicit-conversion

我正在从服务器上反序列化一些JSON,这在大多数情况下很简单:

{
    "id": "ABC123"
    "number" 1234,
    "configured_perspective": "ComplexPerspective[WithOptions,Encoded]"
}

但是,不幸的是,当嵌套对象会更好时,服务器使用奇怪的组合字符串的情况下,该“ configured_perspective”属性是一个不幸的情况。

为减轻.NET用户的痛苦,我将其转换为对象模型中的自定义类:

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) + ']';
}

如您所见,我已经组合了一个自定义类Perspective,该类可以与JSON字符串进行来回转换,但是我似乎无法获得Newtonsoft JSON来自动将字符串转换为我的Perspective类。


我试图让它使用[JsonConstructor]属性来调用字符串构造函数,但它只是使用null来调用构造函数,而不是使用JSON中存在的字符串值。

我的印象是(基于https://stackoverflow.com/a/34186322/529618),JSON.NET将使用隐式/显式字符串转换运算符将JSON中的简单字符串转换为目标类型的实例(如果可用),但似乎忽略它,只返回错误:

  

Newtonsoft.Json.JsonSerializationException:无法找到用于Perspective类型的构造函数。一个类应该具有一个默认构造函数,一个带有参数的构造函数或一个标有JsonConstructor属性的构造函数。路径“ configured_perspective”


我试图避免为Example类编写自定义JsonConverter-我很确定会有一种开箱即用的方式将简单的字符串值转换为非字符串属性类型,我还没有找到。

2 个答案:

答案 0 :(得分:1)

在阅读您的最后一篇文章之前,我实际上写了一个自定义的序列化程序类,但是随后我有了一个主意。

如果我们修改了示例而不将其序列化到Perspective,该怎么办?而且我们对此有些懒惰?

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;

}

这不是完美的,我们保留了字符串浪费的内存,但是它可能对您有效。

答案 1 :(得分:0)

目前,我在@Jlalonde的建议上使用以下变体-进行了调整,以使用户体验不会改变,同时利用JSON.NET也在寻找私有属性这一事实。

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);
    }
}