将JSON对象反序列化为c#类,该类包装类型化字典字段

本文关键字:包装类 包装 类型化 字典 字段 反序列化 对象 JSON | 更新日期: 2023-09-27 18:04:05

我有一个JSON对象,我从我的REST API服务器,看起来像这样:

"settings": {
  "assets.last_updated_at": "2016-08-24T23:40:26.442Z",
  "data.version": 34
}

通常我将对象反序列化为stringobject的字典,但我想提供帮助方法来获得值的强类型版本。我用的是JSON。NET来反序列化JSON对象。以下是我目前得到的:

[JsonConverter(typeof(SettingsJsonConverter))]
public class Settings
{
    [JsonIgnore]
    public Dictionary<string, string> Entries { get; private set; }
    public Settings()
    {
        this.Entries = new Dictionary<string, string>();
    }
}

为了在类中包装字典,似乎我需要创建一个自定义JsonConverter,目前看起来像这样:

public class SettingsJsonConverter : JsonConverter
{
    #region implemented abstract members of JsonConverter
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject settingsObj = JObject.Load(reader);
        Settings settings = new Settings();
        foreach(KeyValuePair<string, JToken> entry in settingsObj)
        {
            settings.Entries.Add(entry.Key, entry.Value.ToString());
        }
        return settings;
    }
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Settings);
    }
    #endregion
}

现在很明显,我可以在我的Settings类中创建方法,如GetDate,它获取给定键的值,并使用ISO字符串值创建一个新的DateTime对象。然而,JSON。. NET已经提供了做我想做的事情的工具,所以我宁愿对我迭代的任何值使用其内置的反序列化,而不是自己做。

似乎这样做的地方将在SettingsJsonConverter#ReadJsonforeach循环内,但我不太确定如何获得给定JTokenType(不是JTokenType,标准c# Type),因此我可以将其传递到JToken#ToObject(Type)。或者,我如何迭代JsonReader以使用已经反序列化的值填充我的内部Entries字典,这样我只需要在Settings的助手方法中进行简单的强制转换?下面是我希望我的Settings类的样子:

[JsonConverter(typeof(SettingsJsonConverter))]
public class Settings
{
    [JsonIgnore]
    public Dictionary<string, object> Entries { get; private set; }
    public Settings()
    {
        this.Entries = new Dictionary<string, object>();
    }
    public DateTime GetDate(string key)
    {
        return (DateTime)this.Entries[key];
    }
}

我这样做对吗?

将JSON对象反序列化为c#类,该类包装类型化字典字段

您可以直接反序列化为Dictionary<string, JToken>,并在需要时使用类型强制转换,因此您不需要Settings类或自定义转换器。它看起来不像您的解决方案那么好,但代码更简单:

var settings = JsonConvert.DeserializeObject<Dictionary<string, JToken>>(json);
var date = (DateTime) settings["key"];

如果您想保留您的Settings类,我建议您使用上面的行来反序列化字典,并在Settings中使用dictionary参数创建一个新的构造函数,这样您最终会得到两个构造函数,一个创建新字典,另一个使用给定的字典创建新字典。(不要重用形参字典本身,因为你永远不知道调用者之后会对字典做什么。)

public Settings(Dictionary<string, JToken> dict)
{
    Entries = new Dictionary<string, JToken>(dict);
}
顺便说一下,您可以删除JsonIgnore属性,因为您有一个自定义的转换器类。

首先我们要为你相应的json做一个模型。

{
  "settings": {
          "assets.last_updated_at": "2016-08-24T23:40:26.442Z",
        "data.version": 34
   }
}

CSharp模型:

public class Settings
    {
        [JsonProperty("assets.last_updated_at")]
        public string assets_last_updated_at { get; set; }
        [JsonProperty("data.version")]
        public int data_version { get; set; }
       // Add other property here...
    }
    public class RootObject
    {
        public Settings settings { get; set; }
    }

将Json字符串反序列化到Model:

RootObject rootObject = JsonConvert.DeserializeObject<RootObject>("Put your Json String");