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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用JSON.Net将字符串属性值反序列化为类实例相关的知识,希望对你有一定的参考价值。

我正在从服务器反序列化一些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 - 我很确定会有一种开箱即用的方法将简单的字符串值转换为非字符串属性类型,我只是避难所找到了它。

答案

在阅读你的文章的最后一篇文章之前,我实际上写了一个自定义序列化程序类,但后来我有了一个想法。

如果我们将示例修改为不将其序列化为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;

}

它并不完美,我们坚持浪费内存的字符串,但它可能对你有用。

另一答案

目前我在@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);
    }
}

以上是关于使用JSON.Net将字符串属性值反序列化为类实例的主要内容,如果未能解决你的问题,请参考以下文章

使用 XmlSerializer 将空 xml 属性值反序列化为可为空的 int 属性

为啥使用 Json.NET 序列化为 json 字符串时缺少 DriveInfo 的属性?

将json键值反序列化为字典c#

将 JSON 反序列化为 C# 类,其中 JSON 中的属性名称是动态的

根据字段值反序列化为密封子类

JSON.NET 将对象 序列化为 JSON字符串时,能否指定,某个属性不被转化。