将JSON对象反序列化为包装类型为Dictionary

时间:2016-08-25 06:09:45

标签: c# json json.net deserialization

我有一个从我的REST API服务器获得的JSON对象,如下所示:

"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已经提供了我想要做的设施,所以我宁愿使用它内置的反序列化来迭代任何值,而不是自己做。

似乎这样做的地方会在foreach的{​​{1}}循环中,但我不太确定如何获取SettingsJsonConverter#ReadJson(不是Type 1}},给定JTokenType的标准C#Type),因此我可以将其传递给JToken。或者,我如何迭代JToken#ToObject(Type)以使用已反序列化的值填充我的内部JsonReader字典,这样我只需要在Entries中的辅助方法中进行简单的强制转换?以下是我喜欢我的Settings课程的方式:

Settings

我是否正确地做到了这一点?几乎感觉就像我忽视了一些简单的方式。

2 个答案:

答案 0 :(得分:0)

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

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

如果您想保留Settings课程,我建议您使用上面的行反序列化字典,并在Settings中使用字典参数创建新的构造函数,这样您就可以了最后得到两个构造函数,一个用于创建新字典,另一个用于创建新字典。 (不要重复使用参数字典本身,你永远不知道调用者之后会对字典做什么。)

public Settings(Dictionary<string, JToken> dict)
{
    Entries = new Dictionary<string, JToken>(dict);
}

顺便说一句,您可以删除JsonIgnore属性,因为您有自定义转换器类。

答案 1 :(得分:0)

首先,我们必须为你对应的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");

希望得到这个帮助。