反序列化具有多个数据类型的JSON文件

反序列化具有多个数据类型的JSON文件

本文介绍了反序列化具有多个数据类型的JSON文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想分析Telegram-Chats,所以我以JSON格式导出了聊天,并想将其反序列化到我的分析软件中.

I wanted to analyze Telegram-Chats so I exported a chat in JSON format and wanted to deserialize it into my analyzing software.

    {
      "id": 397910,
      "type": "message",
      "date": "2018-02-21T10:27:59",
      "edited": "1970-01-01T01:00:00",
      "from": "Username",
      "from_id": 39033284,
      "text": "Some Text"
    }

所以我用了这个简单的代码来读取JSON

So I've used this simple code to read the JSON

    List<JSONObject> jsonObjects = JsonConvert.DeserializeObject<List<JSONObject>>(File.ReadAllText(openFileDialog.FileName));

    public class JSONObject
    {
       public int ID;
       public string type;
       public string date;
       public string edited;
       public string from;
       public int fromID;
       public string photo;
       public int width;
       public int height;
       public string text;
    }

这对于前525个数据集来说非常顺利,但是之后,由于一致性问题",我在反序列化数据时遇到了麻烦.文本的数据类型有时会更改为数组.

This went very well for the first 525 datasets but afterwards, I had trouble deserializing the data because of "consistency issues". The Datatype of the text sometimes changes to an array.

    {
       "id": 397911,
       "type": "message",
       "date": "2018-02-21T10:31:47",
       "edited": "1970-01-01T01:00:00",
       "from": "Username",
       "from_id": 272964614,
       "text": [
          "Some Text ",
          {
             "type": "mention",
             "text": "@school"
          },
          " Some Text"
       ]
    }

我也找到了这个数据集

    {
       "id": 397904,
       "type": "message",
       "date": "2018-02-21T10:18:12",
       "edited": "1970-01-01T01:00:00",
       "from": "Username",
       "from_id": 39033284,
       "text": [
          {
             "type": "link",
             "text": "google.com"
          },
          "\n\nSome Text"
        ]
    }

当数据显示出这种不一致时,我不知道如何反序列化数据.

I don't know how I deserialize the data when it shows this kind of inconsistency.

推荐答案

由于属性很复杂,因此您需要编写自己的反序列化逻辑.

as your property is complex, you'll need to write your own de-serialization logic.

这是我的,但这只是一个例子:

Here's mine, but it's just an example :

  • 首先,您的text属性似乎是
    • 单个值
    • 或值数组
    • First of all, your text property seems to be
      • A single value
      • Or an array of values

      在这种情况下,我将获得始终列表"结果,具有单个值的情况将只是具有一个条目的列表.

      In this case, I'll go for an "always list" result, the case with a single value will just be a list with one entry.

      public List<TextProperty> text;
      

      • 该值也可以是
        • 单个字符串值
        • 具有字符串值和元数据(文本类型)的对象
          • The value can also be
            • A single string value
            • An object with the string value and a meta datum (text type)
            • 同样,如果是字符串,我会去找一个没有类型的总是对象"

              Again, I'll go for an "always object" with no type if it's string only

              public class TextProperty
              {
                  public string text { get; set; }
                  public string type { get; set; }
              }
              

              然后,您必须创建自己的Converter来处理此问题,您只需从JsonConverter继承并实现逻辑

              Then you have to make your own Converter to handle this, you just have to inherit from JsonConverter and implement the logic

              public class TextPropertyConverter : JsonConverter
              {
                  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
                  {
                      throw new NotImplementedException(); // not covered here
                  }
              
                  // A value can be either single string or object
                  // Return a TextProperty in both cases
                  private TextProperty ParseValue(JToken value)
                  {
                      switch(value.Type)
                      {
                          case JTokenType.String:
                              return new TextProperty { text = value.ToObject<string>() };
              
                          case JTokenType.Object:
                              return value.ToObject<TextProperty>();
              
                          default:
                              return null;
                      }
                  }
              
                  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
                  {
                      // You'll start either with a single value (we'll convert to list of one value) or an array (list of several values then)
                      switch(reader.TokenType)
                      {
                          case JsonToken.String:
                          case JsonToken.StartObject:
                              return new List<TextProperty> { ParseValue(JToken.Load(reader)) };
              
                          case JsonToken.StartArray:
                              var a = JArray.Load(reader);
                              var l = new List<TextProperty>();
                              foreach(var v in a)
                                  l.Add(ParseValue(v));
                              return l;
              
                          default:
                              return null;
                      }
                  }
              
                  public override bool CanConvert(Type objectType) => false;
              }
              

              我认为所有情况都应该涵盖

              I think all cases should be covered

              要使用它,只需将JsonConverter属性添加到目标属性

              To use it, simply add the JsonConverter attribute to the target property

              public class JSONObject
              {
                  public int id;
                  public string type;
                  public string date;
                  public string edited;
                  public string from;
                  public int from_id;
                  public string photo;
                  public int width;
                  public int height;
              
                  [JsonConverter(typeof(TextPropertyConverter))]
                  public List<TextProperty> text;
              }
              

              然后对其进行测试:

              static void Main(string[] args)
                  {
                      string json = @"
                      [
                          {
                            ""id"": 397910,
                            ""type"": ""message"",
                            ""date"": ""2018-02-21T10:27:59"",
                            ""edited"": ""1970-01-01T01:00:00"",
                            ""from"": ""Username"",
                            ""from_id"": 39033284,
                            ""text"": ""Some Text""
                          },
              
                          {
                             ""id"": 397911,
                             ""type"": ""message"",
                             ""date"": ""2018-02-21T10:31:47"",
                             ""edited"": ""1970-01-01T01:00:00"",
                             ""from"": ""Username"",
                             ""from_id"": 272964614,
                             ""text"": [
                                ""Some Text "",
                                {
                                   ""type"": ""mention"",
                                   ""text"": ""@school""
                                },
                                "" Some Text""
                             ]
                          }
                      ]";
              
                      List<JSONObject> jsonObjects = JsonConvert.DeserializeObject<List<JSONObject>>(json);
              
                      Console.Read();
                  }
              

              结果如下:

              这篇关于反序列化具有多个数据类型的JSON文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 22:51