【问题标题】:Deserialize List<string> from Json to List<object>将 Json 中的 List<string> 反序列化为 List<object>
【发布时间】:2018-01-09 22:02:17
【问题描述】:

我有以下 json 字符串作为我的问题的示例:

{
    "Code": "Admin",
    "Groups":
    [
        "Administrator",
        "Superuser",
        "User"
    ]
}

我还有一个名为 User 的类,代码如下...

[JsonObject(MemberSerialization.OptIn)]
public class User
{
    public User (string code)
    {
        this.Code = code;
    }

    [JsonProperty]
    public string Code { get; set; }

    [JsonProperty("Groups")]
    private List<UserGroup> groups;
    public List<UserGroup> Groups
    {
       if (groups == null)
           groups = new List<UserGroup>();
       return groups;
    }
}

... 和一个名为 UserGroup 的类——对于这个例子——只有这几行代码:

public class UserGroup
{
    public UserGroup (string code)
    {
        this.Code = code;

        // Some code to fill all the other properties, just by knowing the code.
    }

    public string Code { get; set; }

    // More properties
}

现在,我想要的是上面显示的 JSON 字符串将被反序列化为 User 的实例,并且“Groups”数组中的所有字符串都应反序列化为 List&lt;UserGroup&gt;,其中每个字符串都有实例。 另外 - 反过来 - 是否应该将用户序列化为 JSON 字符串,其中仅包含所包含 UserGroups 的 Code 属性。

我没有正常反序列化,但我创建了一个用户实例并使用此代码填充它...

Newtonsoft.Json.JsonConvert.PopulateObject(jsonString, myUserInstance);

...但是如果我使用上面显示的 JSON 字符串运行代码,我得到的只是以下异常:

Newtonsoft.Json.JsonSerializationException: 'Error converting value "Administrator" to type 'UserGroup'.

我的最后一个要求是,只有在我序列化 User 时,我才希望将 UserGroup 序列化为字符串数组。当我将 UserGroup 独立序列化为根对象时,它应该正常序列化(具有所有属性)。 (相比之下,Json.Net: Serialize/Deserialize property as a value, not as an object 中的对象在所有情况下都被序列化为字符串。)

【问题讨论】:

  • 两个选项。创建一个知道如何处理转换的自定义 JsonConverter 或向类添加隐式运算符以知道如何从字符串转换
  • 我是否必须创建一个从 String 到 UserGroup 的 JsonConverter,反之则从 string 到 List?添加隐式运算符是什么意思?
  • 只是好奇,为什么不直接用这个呢? [JsonProperty("Groups")] public string[] Groups { get;放; }
  • 因为 UserGroup 不仅包含 Code 属性。这只是为了更容易理解。
  • 所以,你输入的 json 字符串更像这样..{"Code":"Admin","Groups":[{"Code":"Administrator",...},{" Code":"SuperUser",...}]} 而不是像帖子中的数组。

标签: c# json list serialization


【解决方案1】:

Administrator 是一个字符串,UserGroup 是一个对象,所以这是类型不匹配。您的代码中列出的场景的有效 JSON 是:

{
    "Code": "Admin",
    "Groups":
    [
        {
            "Code":"Administrator"
        },
        {
            "Code":"Superuser"
        },
        {
            "Code":"User"
        }
    ]
}

【讨论】:

  • 通常这是完全正确的,但在我的示例中,我不想将 UserGroup 的整个对象结构保存在 JSON 字符串中,而只保存代码。 code 属性足以让我的代码获取整个 UserGroup 实例。因此,为了不保存冗余数据(我知道,这是 JSON 的一个几乎必不可少的部分),我只想保存 JSON 中 code 属性中的字符串,并且还希望反序列化仅从代码字符串。
【解决方案2】:

你将不得不为UserGroup写一个转换器

这是一个基于问题中描述的简单转换器

public class UserGroupJsonConverter : JsonConverter {

    public override bool CanConvert(Type objectType) {
        return typeof(UserGroup) == objectType;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
        return new UserGroup((string)reader.Value);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        writer.WriteValue(((UserGroup)value).Code);
    }
}

然后通过设置JsonProperty 属性的ItemConverterType 来更新User 以了解转换器

[JsonObject(MemberSerialization.OptIn)]
public class User {
    public User(string code) {
        this.Code = code;
    }

    [JsonProperty]
    public string Code { get; set; }

    private List<UserGroup> groups;
    [JsonProperty("Groups", ItemConverterType = typeof(UserGroupJsonConverter))]
    public List<UserGroup> Groups {
        get {
            if (groups == null)
                groups = new List<UserGroup>();
            return groups;
        }
    }
}

这将允许示例中的 JSON

{
    "Code": "Admin",
    "Groups":
    [
        "Administrator",
        "Superuser",
        "User"
    ]
}

根据需要反序列化

var user = JsonConvert.DeserializeObject<User>(json);

并被序列化回相同的格式。

var json = JsonConvert.SerializeObject(user);

【讨论】:

  • 如果我这样做,例如不想序列化我的用户,但也许是用户组本身,它不使用这个转换器(如果我不告诉它) ,但会正常序列化它,使用属性名称等,对吧?
  • @ChristophMett,是的。在上面的示例中,该属性仅应用于User 对象上的Groups 属性。如果您只想自己序列化 UserGroup 对象,则转换器不适用。
猜你喜欢
  • 2021-06-14
  • 1970-01-01
  • 2014-02-08
  • 2017-01-15
  • 2020-05-06
  • 2018-09-10
  • 2017-05-21
  • 2018-10-06
  • 1970-01-01
相关资源
最近更新 更多