Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 一次反序列化一个json数组流项_C#_Json_Serialization_Stream_Json.net - Fatal编程技术网

C# 一次反序列化一个json数组流项

C# 一次反序列化一个json数组流项,c#,json,serialization,stream,json.net,C#,Json,Serialization,Stream,Json.net,我将大型对象数组序列化为json http响应流。现在,我想一次一个地从流中反序列化这些对象。有没有任何c#库可以让我这样做?我已经看过json.net,但似乎我必须立即反序列化完整的对象数组 [{large json object},{large json object}.....] 澄清:我想一次从流中读取一个json对象并对其进行反序列化。为了增量读取json,您需要将JsonTextReader与StreamReader结合使用。但是,您不必从读取器手动读取所有JSON。您应该能够利用

我将大型对象数组序列化为json http响应流。现在,我想一次一个地从流中反序列化这些对象。有没有任何c#库可以让我这样做?我已经看过json.net,但似乎我必须立即反序列化完整的对象数组

[{large json object},{large json object}.....]

澄清:我想一次从流中读取一个json对象并对其进行反序列化。

为了增量读取json,您需要将
JsonTextReader
StreamReader
结合使用。但是,您不必从读取器手动读取所有JSON。您应该能够利用Linq to JSON API从读取器加载每个大型对象,以便更轻松地使用它

举个简单的例子,假设我有一个JSON文件,看起来像这样:

[
  {
    "name": "foo",
    "id": 1
  },
  {
    "name": "bar",
    "id": 2
  },
  {
    "name": "baz",
    "id": 3
  }
]
1 - foo
2 - bar
3 - baz
   {
      "Order": [
          { order object 1},
          { order object 2},
          {...}
          { order object 10000},
      ]
   }
从文件中增量读取的代码可能如下所示。(在您的情况下,您将使用响应流替换文件流。)

上面的输出如下所示:

[
  {
    "name": "foo",
    "id": 1
  },
  {
    "name": "bar",
    "id": 2
  },
  {
    "name": "baz",
    "id": 3
  }
]
1 - foo
2 - bar
3 - baz
   {
      "Order": [
          { order object 1},
          { order object 2},
          {...}
          { order object 10000},
      ]
   }

我简化了我的解析器/反序列化器的一个示例/测试,以更直接地回答这个问题的用例

以下是测试数据:

(参见fathers.json.txt)

下面是示例代码:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Text;

    // Our stuff
    using System.Text.Json;

//...

    public class FathersData
    {
        public Father[] fathers { get; set; }
    }

    public class Someone
    {
        public string name { get; set; }
    }

    public class Father : Someone
    {
        public int id { get; set; }
        public bool married { get; set; }
        // Lists...
        public List<Son> sons { get; set; }
        // ... or arrays for collections, that's fine:
        public Daughter[] daughters { get; set; }
    }

    public class Child : Someone
    {
        public int age { get; set; }
    }

    public class Son : Child
    {
    }

    public class Daughter : Child
    {
        public string maidenName { get; set; }
    }

//...

    static void FilteredFatherStreamTestSimplified()
    {
        // Get our parser:
        var parser = new JsonParser();

        // (Note this will be invoked thanks to the "filters" dictionary below)
        Func<object, object> filteredFatherStreamCallback = obj =>
        {
            Father father = (obj as Father);
            // Output only the individual fathers that the filters decided to keep (i.e., when obj.Type equals typeof(Father)),
            // but don't output (even once) the resulting array (i.e., when obj.Type equals typeof(Father[])):
            if (father != null)
            {
                Console.WriteLine("\t\tId : {0}\t\tName : {1}", father.id, father.name);
            }
            // Do not project the filtered data in any specific way otherwise,
            // just return it deserialized as-is:
            return obj;
        };

        // Prepare our filter, and thus:
        // 1) we want only the last five (5) fathers (array index in the resulting "Father[]" >= 29,995),
        // (assuming we somehow have prior knowledge that the total count is 30,000)
        // and for each of them,
        // 2) we're interested in deserializing them with only their "id" and "name" properties
        var filters = 
            new Dictionary<Type, Func<Type, object, object, int, Func<object, object>>>
            {
                // We don't care about anything but these 2 properties:
                {
                    typeof(Father), // Note the type
                    (type, obj, key, index) =>
                        ((key as string) == "id" || (key as string) == "name") ?
                        filteredFatherStreamCallback :
                        JsonParser.Skip
                },
                // We want to pick only the last 5 fathers from the source:
                {
                    typeof(Father[]), // Note the type
                    (type, obj, key, index) =>
                        (index >= 29995) ?
                        filteredFatherStreamCallback :
                        JsonParser.Skip
                }
            };

        // Read, parse, and deserialize fathers.json.txt in a streamed fashion,
        // and using the above filters, along with the callback we've set up:
        using (var reader = new System.IO.StreamReader(FATHERS_TEST_FILE_PATH))
        {
            FathersData data = parser.Parse<FathersData>(reader, filters);

            System.Diagnostics.Debug.Assert
            (
                (data != null) &&
                (data.fathers != null) &&
                (data.fathers.Length == 5)
            );
            foreach (var i in Enumerable.Range(29995, 5))
                System.Diagnostics.Debug.Assert
                (
                    (data.fathers[i - 29995].id == i) &&
                    !String.IsNullOrEmpty(data.fathers[i - 29995].name)
                );
        }
        Console.ReadKey();
    }
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用系统文本;
//我们的东西
使用System.Text.Json;
//...
公共类父类数据
{
公共父[]父{get;set;}
}
公开课某人
{
公共字符串名称{get;set;}
}
公共课父亲:有人
{
公共int id{get;set;}
公共布尔已婚{get;set;}
//列表。。。
公共列表{get;set;}
//…或集合的数组,这很好:
公共子元素[]子元素{get;set;}
}
公共班级的孩子:某人
{
公共整数{get;set;}
}
公营班级儿子:儿童
{
}
公课女儿:儿童
{
公共字符串maidenName{get;set;}
}
//...
静态空过滤器DeFatherstreamTestSimplified()
{
//获取我们的解析器:
var parser=new JsonParser();
//(注意,这将通过下面的“过滤器”字典调用)
Func filteredFatherStreamCallback=obj=>
{
父亲=(obj作为父亲);
//仅输出筛选器决定保留的各个父级(即,当obj.Type等于typeof(父级)时),
//但不要输出(甚至一次)结果数组(即,当obj.Type等于typeof(父[])时):
if(父亲!=null)
{
WriteLine(“\t\tId:{0}\t\t名称:{1}”,father.id,father.name);
}
//不要以任何特定方式投影过滤后的数据,否则,
//只需按原样反序列化它:
返回obj;
};
//准备好我们的过滤器,因此:
//1)我们只需要最后五(5)个父亲(结果“父亲[]”>=29995中的数组索引),
//(假设我们事先知道总数为30000)
//对于他们每一个人,
//2)我们只对它们的“id”和“name”属性进行反序列化
变量过滤器=
新词典
{
//我们只关心以下两个属性:
{
typeof(父亲),//注意类型
(类型、对象、键、索引)=>
((作为字符串的键)=“id”| |(作为字符串的键)=“name”)?
filteredFatherStreamCallback:
JsonParser.Skip
},
//我们只想从来源中挑选最后5位父亲:
{
typeof(父[]),注意类型
(类型、对象、键、索引)=>
(索引>=29995)?
filteredFatherStreamCallback:
JsonParser.Skip
}
};
//以流式方式读取、解析和反序列化fathers.json.txt,
//使用上述过滤器以及我们设置的回调:
使用(var reader=new System.IO.StreamReader(测试文件路径))
{
fathersdatadata=parser.Parse(读取器、过滤器);
System.Diagnostics.Debug.Assert
(
(数据!=null)&&
(data.fathers!=null)&&
(data.dages.Length==5)
);
foreach(可枚举范围(29995,5))中的var i
System.Diagnostics.Debug.Assert
(
(data.fathers[i-29995].id==i)&&
!String.IsNullOrEmpty(data.fathers[i-29995].name)
);
}
Console.ReadKey();
}
其余位可在此处找到:

“HTH,

这是我的解决方案(来自不同来源,但主要基于解决方案),用于将任何通用对象的巨大JSON文件(对象数组)转换为XML文件

JSON如下所示:

[
  {
    "name": "foo",
    "id": 1
  },
  {
    "name": "bar",
    "id": 2
  },
  {
    "name": "baz",
    "id": 3
  }
]
1 - foo
2 - bar
3 - baz
   {
      "Order": [
          { order object 1},
          { order object 2},
          {...}
          { order object 10000},
      ]
   }
输出XML:

<Order>...</Order>
<Order>...</Order>
<Order>...</Order>
。。。
...
...
C#代码:

XmlWriterSettings xws=newxmlwritersettings{omitxmldesclaration=true};
使用(StreamWriter sw=新StreamWriter(xmlFile))
使用(FileStream fs=newfilestream(jsonFile,FileMode.Open,FileAccess.Read))
使用(StreamReader sr=新StreamReader(fs))
使用(JsonTextReader reader=newjsontextreader(sr))
{
//sw.写(“”);
while(reader.Read())
{
if(reader.TokenType==JsonToken.StartArray)
{
while(reader.Read())
{
if(reader.TokenType==JsonToken.StartObject)
{
JObjec