【问题标题】:Is it possible to leave fields as raw text when deserializing?反序列化时是否可以将字段保留为原始文本?
【发布时间】:2021-09-29 10:32:06
【问题描述】:

我有这样的json

{
    "guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
    "status": "complete",
    "type": "colors",    
    "results": {
        "events": [
            {
                "title": "event1",
                "other": {
                    "Red": "red",
                    "Green": "green",
                    "Blue": "blue"
                }
            },
            {
                "title": "event2",
                "other": {
                    "Yelow": "yellow",
                    "Orange": "orange"
                }
            }
        ]
    }
}

反序列化的类看起来像这样

public class Other
{
    public string Red { get; set; }
    public string Green { get; set; }
    public string Blue { get; set; }
    public string Yelow { get; set; }
    public string Orange { get; set; }
}

public class Event
{
    public string title { get; set; }
    public Other other { get; set; }
}

public class Results
{
    public List<Event> events { get; set; }
}

public class Root
{
    public string guid { get; set; }
    public string status { get; set; }
    public string type { get; set; }
    public Results results { get; set; }
}

当我反序列化这个 json 时

var root = JsonConvert.DeserializeObject<Root>(JsonContent); 

一切正常。

问题是json部分"Other"的内容是可变的,我不知道它的完整内容。
我还需要将这些类放入数据库中。

有没有办法将 json 部分 "Other" 反序列化为一个带有原始文本的字符串字段,并看起来像这样:

public class Other
{
    public string AllFieldsFromOtherSectionAsRawText { get; set; }
}

【问题讨论】:

  • 你在使用 Newtonsoft Json.NET,对吗?
  • 您可以将Other 的类型更改为JObject,此时它只是“一些任意的JSON 对象”
  • 是的,Newtonsoft Json.NET。
  • 谢谢@JonSkeet,你拯救了我的一天! :) 你的想法最适合我的场景! :)

标签: c# json json.net


【解决方案1】:

如果您像这样定义 Other 类:

public class Other
{
    public Other(string rawData)
    {
        Content = rawData;
    }
    public string Content { get; }
}

然后您可以编写一个自定义的JsonConverter,它将您的other 节点视为string

class ObjectToStringJsonConverter : JsonConverter
{
    private readonly Type theType;
    public ObjectToStringJsonConverter(Type type) => theType = type;

    public override bool CanConvert(Type objectType) => objectType == theType;

    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)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Object)
        {
            return Activator.CreateInstance(theType, args: token.ToString()); 
        }
        throw new NotSupportedException("The related node is not object");
    }
}

这里唯一的技巧是这一行:

  • Activator.CreateInstance(theType, args: token.ToString());
  • 这里我们创建一个新的Other 实例并将other 节点的字符串表示形式传递给构造函数。

那么用法应该是这样的:

var root = JsonConvert.DeserializeObject<Root>(json, new[] { new ObjectToStringJsonConverter(typeof(Other)) });

【讨论】:

    【解决方案2】:

    Other 不是字典表示吗?

    你不能把它写成字典

    public Dictionary<String,String> other { get; set; }
    

    例子:

        [Newtonsoft.Json.JsonExtensionData]
        public System.Collections.Generic.IDictionary<string, string> other
    

    根据文档,你 DeserializeObject on type Dictionary:

    JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
    

    https://www.newtonsoft.com/json/help/html/DeserializeDictionary.htm

    【讨论】:

    • 这也是我的想法,但我不知道如何设置Newtnsoft.Json反序列化器将其写入字典。
    • JsonExtensionData 用于向对象添加未定义的字段,如果 json 具有字段 A、B、C、D 但您定义的对象具有属性 A、B,则只有 C 和 D 被忽略,除非您有 JsonExtensionData标记的字典在这种情况下它们被添加到,在这种情况下,其他是 json 中定义的项目,因此可以直接反序列化到字典中
    【解决方案3】:

    从您的代码中删除类 Other,并修复 Event 类

    public class Event
    {
        public string title { get; set; }
        [JsonProperty(PropertyName = "other")]
        public Dictionary<string, string> otherDict { get; set; }
        
        [Newtonsoft.Json.JsonIgnore]
        public IEnumerable<string> Other
        {
            get { return  otherDict.Values.ToArray(); }
        }
    
        [Newtonsoft.Json.JsonIgnore]
        public string AllFieldsFromOtherSectionAsRawText
        {
            get { return string.Join(",", Other);  }
        }
    }
    
    

    输出

    {
      "guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
      "status": "complete",
      "type": "colors",
      "results": {
        "events": [
          {
            "title": "event1",
            "other": {
              "Red": "red",
              "Green": "green",
              "Blue": "blue"
            },
            "AllFieldsFromOtherSectionAsRawText": "red,green,blue"
          },
          {
            "title": "event2",
            "other": {
              "Yelow": "yellow",
              "Orange": "orange"
            },
            "AllFieldsFromOtherSectionAsRawText": "yellow,orange"
          }
        ]
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      • 1970-01-01
      • 1970-01-01
      • 2018-09-28
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      相关资源
      最近更新 更多