当目标是抽象对象时,Json.net反序列化问题

本文关键字:Json net 反序列化 问题 目标 抽象 对象 | 更新日期: 2023-09-27 18:21:36

我正在使用一个返回json的服务。

我有一个键值对象,其中键是string,值是object,我知道在哪里根据键投射对象。

它看起来像:

{
  "key1": "This is key 1",
  "key2": 12,
  "key3": ["Key 3 first item", "Key 3 second item"]
}

对于简单类型(例如)stringslongint等,没有问题
当我收到array(键3)时,问题就开始了。

我的c#代码看起来像这样:

Dictionary<string, object> values = GetValuesFromTheService();
string str = (string)values["key1"]; // Ok
long lng = (long)values["key2"]; // Ok
List<string> strs = (List<string>)values["key3"]; // BAD

key3实际上是JArray,而不是List<string>——我想这是因为我使用object作为值,而不是更具体(List<object>也会比JArray更好)。

对此我能做些什么吗?

当目标是抽象对象时,Json.net反序列化问题

我在尝试(反)序列化一些自定义枚举时也遇到了类似的情况。对于解决方案,我创建了一个自定义的JsonConvertor。这是我使用的代码。。。

public class EnumerationConverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var enm = (Enumeration)value;
            writer.WriteValue(enm.Value);
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.Value == null)
            {
                return null;
            }
            int value;
            if (reader.ValueType == typeof(Int64))
            {
                value = Convert.ToInt32(reader.Value);
            }
            else
            {
                value = (int)reader.Value;
            }
            return Enumeration.FromValueOrDefault(objectType, value);
        }
        public override bool CanConvert(Type objectType)
        {
            if (objectType.BaseType == null) return false;
            return objectType.BaseType.Name == "Enumeration";
        }
    }

然后,当我想调用它并将json拉回到我的对象中时,这是一行。。。

JsonConvert.DeserializeObject<List<CustomObjectDto>>(req.Content.ReadAsStringAsync().Result, new EnumerationConverter());

好的是,它变得普遍可用,CustomObjectDto可以在其中有一个这个神奇字典的实例作为属性。。。甚至多个。。。并且将仅对根据转换器中的逻辑匹配的属性应用转换。。。希望能有所帮助。

这里有一个类似主题的链接-->http://blog.maskalik.com/asp-net/json-net-implement-custom-serialization/

您应该能够将整个对象解析为jObject,然后选择所需类型的键。这是未经测试的基本想法。

var j = JObject.Parse(GetValuesFromTheService());
string str = (string)j.SelectToken("key1");
long lng = (long)j.SelectToken("key2");
var strs = (List<string>)j.SelectToken("key3");

如果key3string值的JArray,则可以执行以下操作:

List<string> strs = ((JArray)values["key3"]).Select(t => t.Value<string>()).ToList();