2016-11-03 3 views
-1

私はAPIから10000人のデータを取得する必要があるシナリオを持っています。残念ながら、APIプロバイダはページングを実行していません(悲しい)。今私はこのケースを扱う際には非常に慎重でなければならない。私がやりたいことは、このデータをダウンロードしてJArrayに保存して、各オブジェクトで実行したい処理を追加することだけです。HttpClientでAPIから巨大な応答を取得し、JArrayに格納する

HttpClientを使用して巨大なデータをフェッチしてJArrayに格納するのにベストプラクティスを続けましたが、Newtonsoft.JsonではSystem.OutOfMemoryExceptionを取得しました。まさに私が間違っているのは何

public async Task<JArray> GetContactsObject(ConnectorToken token) 
{ 
     JArray contacts = new JArray(); 

     try 
     { 
      using (var client = new HttpClient()) 
      { 

       client.Timeout = TimeSpan.FromMinutes(10); 

       string requestUrl = "<api_uri>"; 


       client.DefaultRequestHeaders.Add("Authorization", GenearateHeaders("GET", requestUrl, token)); 

       client.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/json"); 

       using (Stream s = await client.GetStreamAsync(requestUrl)) 
       using (StreamReader sr = new StreamReader(s)) 
       using (JsonReader reader = new JsonTextReader(sr)) 
       { 
        contacts = JArray.Load(reader); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      _logger.Fatal(ex); 
     } 
     return contacts; 
} 

- ここ

は私のコードブロックがどのように見えるかですか? APIの応答は巨大で、10,000件の連絡先があり、応答のサイズは約70-80MBです。

更新スニペット - まだ例外がスローされますが、改善私は応答が "唯一" であってもよい

public async Task<MailPlusContacts> GetContactsObject(ConnectorToken token) 
     { 
      MailPlusContacts contacts = new MailPlusContacts(); 

      try 
      { 
       using (var client = new HttpClient()) 
       { 

        client.Timeout = TimeSpan.FromMinutes(10); 

        string requestUrl = "<api_uri>"; 


        client.DefaultRequestHeaders.Add("Authorization", GenearateHeaders("GET", requestUrl, token)); 

        client.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/json"); 



        using (Stream s = await client.GetStreamAsync(requestUrl)) 
        using (StreamReader sr = new StreamReader(s)) 
        using (JsonTextReader reader = new JsonTextReader(sr)) 
        { 

         while (reader.Read()) 
         { 
          if (reader.TokenType == JsonToken.StartObject) 
          { 
           // Load each object from the stream and do something with it 
           JObject obj = JObject.Load(reader); 
           contacts.Contacts.Add(obj); 
          } 


         } 
        } 

       } 
      } 
      catch (Exception ex) 
      { 


      } 

      return contacts; 
     } 

サンプルJSON(1つのオブジェクト、これらの10Kを考える)

[ 
    { 
     "externalId": "4D8C802F4DE244248D97E8C80F628AF3", 
     "created": 1471413089000, 
     "encryptedId": "bbhjZi4UYIiYnnZ", 
     "testGroup": false, 
     "lastChanged": 1476683221000, 
     "temporary": false, 
     "properties": { 
      "prop1": "11:09", 
      "birthdate": "1991-07-01", 
      "freeField1": "*1000000000*", 
      "freeField2": "Y", 
      "street": "Shivaji Nagar", 
      "houseNumber": "123", 
      "city": "Pune", 
      "list4": [ 
       { 
        "description": "dropdown item", 
        "bit": 1, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 2", 
        "bit": 2, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 3", 
        "bit": 4, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 23-1-2016", 
        "bit": 8, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 2 23-1-2016", 
        "bit": 16, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 2 27-1-2016", 
        "bit": 32, 
        "enabled": false 
       }, 
       { 
        "description": "Meeloopdagen", 
        "bit": 64, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 2 5-3-2016", 
        "bit": 128, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 5-3-2016", 
        "bit": 256, 
        "enabled": true 
       }, 
       { 
        "description": "dropdown item 2 Chemie 1-3-2016", 
        "bit": 512, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 2 Chemie 8-3-2016", 
        "bit": 1024, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 23-4-2016", 
        "bit": 2048, 
        "enabled": false 
       }, 
       { 
        "description": "dropdown item 2 23-4-2016", 
        "bit": 4096, 
        "enabled": false 
       } 
      ], 
      "list5": [ 
       { 
        "description": "Ja", 
        "bit": 1, 
        "enabled": true 
       }, 
       { 
        "description": "Nee", 
        "bit": 2, 
        "enabled": false 
       } 
      ], 
      "list2": [ 
       { 
        "description": "Test Werk en Test", 
        "bit": 1, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test Test", 
        "bit": 2, 
        "enabled": false 
       }, 
       { 
        "description": "Test Psychologie", 
        "bit": 4, 
        "enabled": false 
       }, 
       { 
        "description": "Test Therapie", 
        "bit": 8, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 16, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 32, 
        "enabled": false 
       }, 
       { 
        "description": "Bio-Test", 
        "bit": 64, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 128, 
        "enabled": false 
       }, 
       { 
        "description": "Test Economie", 
        "bit": 256, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 512, 
        "enabled": false 
       }, 
       { 
        "description": "HBO-Test", 
        "bit": 1024, 
        "enabled": false 
       }, 
       { 
        "description": "Sociaal Test Test", 
        "bit": 2048, 
        "enabled": false 
       }, 
       { 
        "description": "Human Test Test", 
        "bit": 4096, 
        "enabled": false 
       }, 
       { 
        "description": "Test en Test", 
        "bit": 8192, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 16384, 
        "enabled": false 
       } 
      ], 
      "postalCode": "1201AX", 
      "list3": [ 
       { 
        "description": "Test 1", 
        "bit": 1, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 2, 
        "enabled": false 
       }, 
       { 
        "description": "DTest 1", 
        "bit": 4, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 8, 
        "enabled": false 
       }, 
       { 
        "description": "LTest 1", 
        "bit": 16, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 32, 
        "enabled": false 
       }, 
       { 
        "description": "PTest 1", 
        "bit": 64, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 128, 
        "enabled": false 
       }, 
       { 
        "description": "STest 1", 
        "bit": 256, 
        "enabled": false 
       }, 
       { 
        "description": "TTest 1", 
        "bit": 512, 
        "enabled": false 
       }, 
       { 
        "description": "MTest 1", 
        "bit": 1024, 
        "enabled": false 
       }, 
       { 
        "description": "KTest 1", 
        "bit": 2048, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 4096, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1e", 
        "bit": 8192, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 16384, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1n", 
        "bit": 32768, 
        "enabled": false 
       }, 
       { 
        "description": "PTest 1jk", 
        "bit": 65536, 
        "enabled": false 
       }, 
       { 
        "description": "BTest 1a", 
        "bit": 131072, 
        "enabled": false 
       }, 
       { 
        "description": "BTest 1ek ", 
        "bit": 262144, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 524288, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 1048576, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1 Economie", 
        "bit": 2097152, 
        "enabled": false 
       }, 
       { 
        "description": "Test ", 
        "bit": 4194304, 
        "enabled": true 
       }, 
       { 
        "description": "HBO-Test", 
        "bit": 8388608, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test Test", 
        "bit": 16777216, 
        "enabled": false 
       }, 
       { 
        "description": "Test in de Test", 
        "bit": 33554432, 
        "enabled": false 
       }, 
       { 
        "description": "Test Resource Test", 
        "bit": 67108864, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test", 
        "bit": 134217728, 
        "enabled": false 
       } 
      ], 
      "phoneNumber": "0793631212", 
      "initials": "Rahul", 
      "list1": [ 
       { 
        "description": "Test 1", 
        "bit": 1, 
        "enabled": false 
       }, 
       { 
        "description": "Test 2", 
        "bit": 2, 
        "enabled": false 
       }, 
       { 
        "description": "Test 3", 
        "bit": 4, 
        "enabled": true 
       }, 
       { 
        "description": "Test 4", 
        "bit": 8, 
        "enabled": false 
       }, 
       { 
        "description": "Test 5", 
        "bit": 16, 
        "enabled": false 
       }, 
       { 
        "description": "Test 6", 
        "bit": 32, 
        "enabled": false 
       }, 
       { 
        "description": "tet7 ", 
        "bit": 64, 
        "enabled": false 
       }, 
       { 
        "description": "Test 8", 
        "bit": 128, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 256, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 512, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 1024, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 2048, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 4096, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 8192, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 16384, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 32768, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 65536, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 131072, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 262144, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 524288, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 1048576, 
        "enabled": true 
       }, 
       { 
        "description": "Test 1 Economie", 
        "bit": 2097152, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 4194304, 
        "enabled": false 
       }, 
       { 
        "description": "HBO-Test 1", 
        "bit": 8388608, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1 ", 
        "bit": 16777216, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 33554432, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 67108864, 
        "enabled": false 
       }, 
       { 
        "description": "Test 1", 
        "bit": 134217728, 
        "enabled": false 
       } 
      ], 
      "gender": "M", 
      "firstName": "Rahul Patil", 
      "list6": [ 
       { 
        "description": "Test", 
        "bit": 1, 
        "enabled": false 
       }, 
       { 
        "description": "Test ", 
        "bit": 2, 
        "enabled": false 
       }, 
       { 
        "description": "Test ", 
        "bit": 4, 
        "enabled": false 
       }, 
       { 
        "description": "Test ", 
        "bit": 8, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test", 
        "bit": 16, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 32, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test Test", 
        "bit": 64, 
        "enabled": false 
       }, 
       { 
        "description": "Test-Test Test", 
        "bit": 128, 
        "enabled": false 
       }, 
       { 
        "description": "Test in de Test", 
        "bit": 256, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test Test Test", 
        "bit": 512, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test", 
        "bit": 1024, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test en Test", 
        "bit": 2048, 
        "enabled": false 
       }, 
       { 
        "description": "Test Therapie", 
        "bit": 4096, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 8192, 
        "enabled": false 
       }, 
       { 
        "description": "Test Resource Test", 
        "bit": 16384, 
        "enabled": false 
       }, 
       { 
        "description": "HBO-Test", 
        "bit": 32768, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 65536, 
        "enabled": false 
       }, 
       { 
        "description": "Test Test", 
        "bit": 131072, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 262144, 
        "enabled": false 
       }, 
       { 
        "description": "Test", 
        "bit": 524288, 
        "enabled": false 
       }, 
       { 
        "description": "Bio-Test", 
        "bit": 1048576, 
        "enabled": false 
       }, 
       { 
        "description": "Test en Test Test", 
        "bit": 2097152, 
        "enabled": false 
       } 
      ], 
      "date1": "2016-09-30", 
      "lastName": "Patil", 
      "organisation": "Test Organization", 
      "email": "[email protected]", 
      "vrij15": "N", 
      "profileFields": [ 
       { 
        "description": "testField", 
        "bit": 1, 
        "enabled": false 
       }, 
       { 
        "description": "test1", 
        "bit": 2, 
        "enabled": true 
       } 
      ], 
      "profileField2": "asd", 
      "numeric1": "10", 
      "profileField1": "asd", 
      "profileField3": "asd" 
     }, 
     "channels": [ 
      { 
       "name": "EMAIL", 
       "value": true 
      }, 
      { 
       "name": "SMS", 
       "value": false 
      } 
     ] 
    } 
] 
+0

とにかく、それぞれのjsonトークンを 'reader'で処理し、配列全体を解析するのではなく、リストまたは辞書に必要な値だけを格納する必要があります。 [JSONをJsonTextReaderで読む](http://www.newtonsoft。com/json/help/html/readjsonwithjsontextreader.htm) – wdosanjos

+0

@ wdosanjos本当の答えを書く必要があります。 – Soviut

+1

私はこれが 'contacts = JArray.Load(reader);'だと思います。あなたの記憶は80メガバイトを超えています。あなたは[Flat buffers](https://google.github.io/flatbuffers/)を検討したいかもしれません。 – peter

答えて

0

を言うだろう80MB(これは膨大なテキストレスポンス)ですが、メモリ内のオブジェクトの階層が大幅に多くの領域を占めることを示すためです。

JSON.NETはストリームから逆シリアル化できるため、文字列全体がメモリにロードされません。代わりに、最も可能性の高い原因は、すべてを単一のcontacts変数に格納し、JArrayがその中のすべての子ノードを解析する可能性が高いという事実です。

メモリが不足するのを防ぐために、ここにはJSON.NET performance tipsがあります。

1

ほとんどの場合、オブジェクトを手動で分割する必要があります。 「JObject.Load(reader);」の作成で発生している構文解析は、この場合、大規模です。

または、JObjectが一定量増加すると、実際に大きなオブジェクトのサイズを変更すると問題が発生する可能性があります。

私はあなたが文字列としてそれを引っ張るより多くの運があると思います。

//Read raw json as a string from the body of the HTTP post, and don’t parse it 
string results = await Request.Content.ReadAsStringAsync(); 

大規模な文字列を解析すると、文字列が最初の文字列であると解析される可能性があります。

しかし、あなたはまだ大きすぎると思うかもしれません。あなたが自分自身の解析の一部をしたいと思うでしょう。それを私はそれを呼び出すよう「楽しさ」の方法やって:

を配列の先頭のオブジェクトを見つけ、その後、ブラケットに 例を数える:あなたのデータは

{"employees":[ 
    {"firstName":"John", "lastName":"Doe"}, 
    {"firstName":"Anna", "lastName":"Smith"}, 
    {"firstName":"Peter", "lastName":"Jones"} 
]} 

を返された場合は、これをしたいと思います:

var headerIndex = '{"employees":['.Length; 
var startIndex = result.IndexOf('{',headerIndex); 
if(startIndex != -1) 
{ 
    var bracketcount = 1; 
    int rowCount; 
    for(rowCount = 0; i < int.MaxValue && bracketcount != 0) 
    { 
     if (result[i] == '{') bracketcount++; 
     if(result[i] == '}') bracketcount--; 
    } 

    var smallerObjectString = result.SubString(0,rowCount); 
    //create a single object and handle it 
+0

私はそれを試してみます;-) –

関連する問題