【问题标题】:Deserializing stringified (quote enclosed) nested objects with Newtonsoft Json.Net使用 Newtonsoft Json.Net 反序列化字符串化(引号括起来)嵌套对象
【发布时间】:2021-11-30 23:48:43
【问题描述】:

Deserializing stringified (quote enclosed) nested objects with Jackson 相同的问题,但针对 C# 和 Newtonsoft Json.Net。问题是如何使用 Json.Net 反序列化 JSON 的嵌套字符串表示。来自 REST 端点的示例响应:

{
    "Id": "abcd1234",
    "Foo": "{\"field1\": "abc", \"field2\": \"def\"}"
}

C# 模型:

public class Model {
    public Guid Id { get; set; }
    public Dictionary<string, string> Foo { get; set; }
}

只是调用JsonConvert.DeserializeObject&lt;Model&gt;(returnedJson) 会出错,因为返回形式的 Foo 是字符串化的 JSON,也就是一个字符串。我们的 JSON 响应中的其他字段也是如此,它们的模型中关联了不同的 Dictionary 类型(例如 Dictionary 和 Dictionary)。

处理这个问题的最简单方法是什么?自定义 JsonConverter 是必要的还是有一些内置的方法来处理它?

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    为了跟进,我使用了与@VijayeR 推荐的非常相似的解决方案,但需要对其进行一些调整,因为它仍然给我带来了一些问题。一个问题是,在使用装饰器时,显然 CanConvert 根本不会被调用,因为 Json.Net 假定您已经为该属性分配了正确的转换器。这对我有用:

    public class NestedJsonConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return true;
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            var jToken = JToken.Load(reader);
    
            if (jToken.Type == JTokenType.String)
            {
                jToken = JToken.Parse((string) jToken);
            }
    
            return jToken.ToObject(objectType);
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    
        public override bool CanWrite => false;
    }
    

    【讨论】:

      【解决方案2】:

      JsonConverter 可能是处理这种隐式转换的最简单方法。这是适合您的情况的一种。

      public class MyConverter: JsonConverter
      {
        public override bool CanConvert(Type objectType)
        {
          return objectType == typeof(string);
        }
      
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
          return JsonConvert.DeserializeObject(reader.Value as string, objectType);
        }
      
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
          throw new NotImplementedException();
        }
      }
      

      然后你用这样的属性装饰那个属性:

      public class Model
      {
        public string Id { get; set; }
        [JsonConverter(typeof(MyConverter))]
        public Dictionary<string, string> Foo { get; set; }
      }
      

      【讨论】:

      • 我想知道您的示例中 CanConvert 和 ReadJson 之间的 objectType。如果在 CanConvert 中 objectType 是字符串,那么不会在 JsonConvert.DeserializeObject 中使用 objectType 将其转换为字符串?或者它们有什么不同?
      • 啊,很好。在这两个函数中传递的 objectType 用于不同的目的。 CanConvert 询问传入的 objectType 是否可以转换(源),而 ReadJson 传递一个 objectType,它告诉要转换为什么(目标)。
      • 感谢您的帮助!在下面添加了对我有用的确切解决方案,但这为我指明了正确的方向,因此我接受了它作为答案:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-29
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      • 1970-01-01
      相关资源
      最近更新 更多