【问题标题】:Read text file with multiple JSON messages读取包含多个 JSON 消息的文本文件
【发布时间】:2015-06-26 08:02:33
【问题描述】:

我有一个包含多个 JSON 消息的文本文件。除了换行之外没有分隔符。我有一个方法,它将采用 JSON 字符串并将其反序列化为某种对象类型。

如何读取文本文件并遍历每个 Json 字符串以便反序列化?

下面是反序列化的方法:

public static T JsonDeserialize<T>(string jsonString)
{
    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
    MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
    T obj = (T)ser.ReadObject(ms);
    return obj;
}

【问题讨论】:

    标签: c# .net json


    【解决方案1】:

    您可以使用 jsonReader.SupportMultipleContent 属性。
    消息换行符、制表符或空格之间的分隔无关紧要。

    SupportMultipleContent 设置一个值 true/false(默认为 false),指示是否可以从连续流中无错误地读取多条 JSON 内容。

    例子:

    public static void Main()
    {   
        string json = @"
        {
            'Name': 'foo',
            'Id': 123
        }{
            'Name': 'bar',
            'Id': 456
        }
        
        //more new line
        {
            'Name': 'jar',
            'Id': 789
        }
        ";
    
         var persons = DeserializeObjects<Person>(json).ToList();
         Console.WriteLine(persons.Count());
         foreach ( var person in persons)
        {
          Console.WriteLine("id: {0}, Name: {1}",person.Id, person.Name);
        }
    

    }

        static IEnumerable<T> DeserializeObjects<T>(string input)
        {
            JsonSerializer serializer = new JsonSerializer();
            using (var strreader = new StringReader(input)) 
            using (var jsonreader = new JsonTextReader(strreader))
            {
                    //you should use this line
                    jsonreader.SupportMultipleContent = true;
                    while (jsonreader.Read()) 
                    {                       
                        yield return  serializer.Deserialize<T>(jsonreader);
                    }
                
            }
        }
         
    
        class Person
        {
          public int Id {get;set;}
          public string  Name {get;set;}
        }
    

    Try it online

    输出:

    3

    id:123,名称:foo

    id:456,名称:bar

    id:789,名称:jar

    【讨论】:

      【解决方案2】:

      我唯一能想到的就是遍历每个字符并计算括号。当括号计数为零时,它将组合字符串添加到列表中。最后,您将获得一个单独的 JSON 字符串列表。

      public List<string> GetJsonItems()
      {
          int BracketCount = 0;
          string ExampleJSON = new StreamReader(@"c:\Json.txt").ReadToEnd();
          List<string> JsonItems = new List<string>();
          StringBuilder Json = new StringBuilder();
      
          foreach (char c in ExampleJSON)
          {
              if (c == '{')
                  ++BracketCount;
              else if (c == '}')
                  --BracketCount;
              Json.Append(c);
      
              if (BracketCount == 0 && c != ' ')
              {
                  JsonItems.Add(Json.ToString());
                  Json = new StringBuilder();
      
              }
          }
          return JsonItems;    
      }
      

      编辑:将代码更改为使用 StringBuilder,现在速度更快。几乎立即解析出一个 2MB 的 JSON 文件。

      【讨论】:

      • 如果ExampleJSON 包含一个带有"}" 的字符串,这是一个有效的json,这将会爆炸。例如{"key": "value}"}.
      【解决方案3】:

      您还可以拆分文本文件并遍历每个 JSON 部分。

      类似这样的:

      void ReadJsonWithLinebreaks(string jsonFilePath)
      {
              string jsonFileContent = File.ReadAllText(jsonFilePath);
              string[] jsonContentSplitted = jsonFileContent.Split(Environment.NewLine.ToCharArray());
      
              // ... iterate through array that contains your JSON content
      }
      

      编辑: 如果您的 JSON 文件带有换行符,请使用 File.ReadAllLines() 而不是 File.ReadAllText

      【讨论】:

        【解决方案4】:

        如果您的 Json 字符串由新行分隔,您可以遍历所有行并使用以下代码解析它们:

        List<YourClass> objects = new List<YourClass>();
        String[] lines = File.ReadAllLines("path\to\file.txt");
        foreach (string line in lines)
        {
            try
            {
                var obj = JsonDeserialize<YourClass>(line);
                objects.Add(obj);
            }
            catch (Exception) { }
        }
        

        如果这对您没有帮助,请发布示例文件。

        【讨论】:

        • 在我看来吃例外是一件非常的坏事。
        • 取决于您的需求。但这只是一个快速的 sn-p,如果反序列化失败,我不知道作者需要做什么。所以这段代码是对解决方案的提示,而不是他应该复制和粘贴的代码。
        【解决方案5】:

        我建议使用StreamReader 类。这有一个 ReadLine() 方法,它会一次返回一个 json 消息。您可以在阅读文件时调用 JsonDeserialize 函数,也可以将所有消息放入一个列表并稍后反序列化它们。

        List<MyClass> deserializedObjects = new List<MyClass>();
        using(var reader = new StreamReader(pathToFile)){
            while(!reader.EndOfStream){
                deserializedObjects.Add(JsonDeserialize<MyClass>(reader.ReadLine()));
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2019-01-31
          • 1970-01-01
          • 2012-07-23
          • 2021-03-03
          • 2017-03-02
          • 2018-06-16
          • 1970-01-01
          • 2018-09-22
          相关资源
          最近更新 更多