将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
}
通常我将对象反序列化为string
到object
的字典,但我想提供帮助方法来获得值的强类型版本。我用的是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#ReadJson
的foreach
循环内,但我不太确定如何获得给定JToken
的Type
(不是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];
}
}
我这样做对吗?
您可以直接反序列化为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");