2017-11-23 16 views
2

저는 Newtonsoft JSON library을 사용하고 있습니다. 가능한 경우 JSON 객체가없이 세트로 반복되도록하고 싶습니다. JSON 객체가 여기에 표시되는 것보다 훨씬 확장되어 있기 때문에 가능한 한 별도의 클래스를 만들어야합니다.Newtonsoft Json.NET을 사용하여 동적 객체 ID가있는 비 배열 JSON을 반복합니다.

이미 herehere으로 보입니다.

내 JSON (게시물의 하단에 미화) : 내가 처음 JsonTextReader과 노력

Dim json As String = "{""result"":{""a326f402f18ab1cd2c4489b07cc3e8f4"":{""id"":""a326f402f18ab1cd2c4489b07cc3e8f4"",""client_id"":30,""broker"":[{""broker_id"": 30,""name"": ""Andrew"",""emailaddress"": ""[email protected]""}],""photos"":[{""small"":""https://www.example.com/30/photos/small/66.1427790195-976.jpg"",""middle"":""https://www.example.com/30/photos/middle/66.1427790195-976.jpg""},{""small"":""https://www.example.com/30/photos/small/31382.1508417843-454.JPG"",""middle"":""https://www.example.com/30/photos/middle/31382.1508417843-454.JPG""}]},""18aec266ec0c01d126e9715bc17124e2"":{""id"":""18aec266ec0c01d126e9715bc17124e2"",""client_id"":30,""broker"":[{""broker_id"": 30,""name"": ""Andrew"",""emailaddress"": ""[email protected]""}],""photos"":[{""small"":""https://www.example.com/30/photos/small/10.1298385655.jpg"",""middle"":""https://www.example.com/30/photos/middle/10.1298385655.jpg""},{""small"":""https://www.example.com/30/photos/small/10.1298385646.jpg"",""middle"":""https://www.example.com/30/photos/middle/10.1298385646.jpg""}]}}}" 

,하지만 빠르게 개별 속성에 액세스하려고 너무 성가신 듯 : 다음

Dim sBuilder As New StringBuilder 
Dim reader As JsonTextReader = New JsonTextReader(New StringReader(json)) 
While reader.Read 
    If reader.Value IsNot Nothing Then 
     sBuilder.Append(String.Format("Token: {0}, Value: {1}", reader.TokenType.ToString, reader.Value.ToString)) 
    Else 
     sBuilder.Append(String.Format("Token: {0}", reader.TokenType.ToString)) 
    End If 
    sBuilder.Append("<br/>") 
End While 

I을 JObjectJArray으로 작업을 시도했습니다. 문제는 제 3 자에 의해 JSON 응답이 생성되고 IMF 형식이 올바르지 않다는 것입니다. result 개체가 실제로 배열이어야하기 때문입니다. 어떻게 result가 배열이 아닌 모든 결과를 통해 루프 및 각 결과는 또한 동적 ID로 식별 할 수 있습니다 또한 결과는 동적 ID를 (a326f402f18ab1cd2c4489b07cc3e8f418aec266ec0c01d126e9715bc17124e2)

그래서, 지금에 직면하고있어이 포함?

의사 코드 : 나는 속성을 선택하려는 그 결과 각각에 대해

  • : 결과의 수를 통해

    1. 루프 (a326f402f18ab1cd2c4489b07cc3e8f418aec266ec0c01d126e9715bc17124e2이 경우 2). 이것은 반드시 내가 _ json(i)("photos")(j)("small")

    같은 뭔가

    Dim photoSmall As String 
    Dim clientId As Integer 
    For i As Integer = 0 To json.count - 1  
        With json(i) 
         clientId = json.client_id   
         For J As Integer= 0 To json.photos.count - 1 
          photoSmall = json.photos(j).small  
         Next J  
        End With 
    Next i 
    

    아름답게 JSON

    { 
        "result": { 
         "a326f402f18ab1cd2c4489b07cc3e8f4": { 
          "id": "a326f402f18ab1cd2c4489b07cc3e8f4", 
          "client_id": 30, 
          "broker": [ 
           { 
            "broker_id": 30, 
            "name": "Andrew", 
            "emailaddress": "[email protected]" 
           } 
          ], 
          "photos": [ 
           { 
            "small": "https://www.example.com/30/photos/small/66.1427790195-976.jpg", 
            "middle": "https://www.example.com/30/photos/middle/66.1427790195-976.jpg" 
           }, 
           { 
            "small": "https://www.example.com/30/photos/small/31382.1508417843-454.JPG", 
            "middle": "https://www.example.com/30/photos/middle/31382.1508417843-454.JPG" 
           } 
          ] 
         }, 
         "18aec266ec0c01d126e9715bc17124e2": { 
          "id": "18aec266ec0c01d126e9715bc17124e2", 
          "client_id": 30, 
          "broker": [ 
           { 
            "broker_id": 30, 
            "name": "Andrew", 
            "emailaddress": "[email protected]" 
           } 
          ], 
          "photos": [ 
           { 
            "small": "https://www.example.com/30/photos/small/10.1298385655.jpg", 
            "middle": "https://www.example.com/30/photos/middle/10.1298385655.jpg" 
           }, 
           { 
            "small": "https://www.example.com/30/photos/small/10.1298385646.jpg", 
            "middle": "https://www.example.com/30/photos/middle/10.1298385646.jpg" 
           } 
          ] 
         } 
        } 
    } 
    

    UPDATE이 잘 될 거라고, 강력한 형식의 수 (json.photos(j).small)를 가지고 있지 않습니다

    이 코드는 배열

    Dim photosTEST As JArray = DirectCast(item("photos"), JArray) 
    Log("photosTEST length", photosTEST.Count.ToString) 
    

    반환하지만이 코드는 오류가 발생합니다 : 정확한 1의 길이가 단지 배열 인 Object reference not set to an instance of an object

    Dim brokers As JArray = DirectCast(item("broker"), JArray) 
    Log("brokers length", brokers.Count.ToString) 
    

    내가 broker 때문에 이해가 안가?

  • 답변

    2

    resultJTokenJObject으로 전송하고 Properties() 컬렉션을 반복 할 수 있습니다. 각 속성의 Value은 관심있는 데이터 (예 : id, client_id,등)가 포함 된 JObject입니다.여기

    은 예입니다

    Dim obj As JObject = JObject.Parse(json) 
    Dim result As JObject = DirectCast(obj("result"), JObject) 
    For Each prop As JProperty In result.Properties() 
    
        Dim item As JObject = DirectCast(prop.Value, JObject) 
        Dim id As String = item("id").Value(Of String) 
        Dim clientId As Integer = item("client_id").Value(Of Integer) 
        Console.WriteLine("id: " & id) 
        Console.WriteLine("client id: " & clientId.ToString()) 
    
        Dim brokers As JArray = DirectCast(item("broker"), JArray) 
        For i As Integer = 0 To brokers.Count - 1 
         Dim broker As JObject = DirectCast(brokers(i), JObject) 
         Dim brokerId As Integer = broker("broker_id").Value(Of Integer) 
         Dim name As String = broker("name").Value(Of String) 
         Dim email As String = broker("emailaddress").Value(Of String) 
         Console.WriteLine("broker " & i.ToString() & " id: " & brokerId) 
         Console.WriteLine("broker " & i.ToString() & " name: " & name) 
         Console.WriteLine("broker " & i.ToString() & " email: " & email) 
        Next 
    
        Dim photos As JArray = DirectCast(item("photos"), JArray) 
        For i As Integer = 0 To photos.Count - 1 
         Dim photo As JObject = DirectCast(photos(i), JObject) 
         Dim small As String = photo("small").Value(Of String) 
         Dim middle As String = photo("middle").Value(Of String) 
         Console.WriteLine("photo " & i.ToString() & " small: " & small) 
         Console.WriteLine("photo " & i.ToString() & " middle: " & middle) 
        Next 
    
        Console.WriteLine() 
    Next 
    

    바이올린 : 코드는 위의 예를 JSON에서 개체의 모든 속성이 항상 존재한다고 가정하는 것이 https://dotnetfiddle.net/ALeiX8

    참고. 특정 속성이 표시되지 않을 수도있는 경우 값을 사용하기 전에 해당 속성에서 Nothing에 대한 검사를 수행해야합니다. 예를 들어 broker 수에 액세스하려고 시도 할 때 Object reference not set to an instance of an object 오류가 발생한다고 언급했습니다. 결과 항목 중 일부에 JSON에 broker 속성이 없음을 알 수 있습니다. 이 경우에는 다음과 같이 Nothing를 확인하기 위해 코드를 변경해야합니다 :

    : 브로커는 이메일 주소가 아닌 경우는

    Dim brokers As JArray = DirectCast(item("broker"), JArray) 
        If brokers IsNot Nothing Then 
         For i As Integer = 0 To brokers.Count - 1 
          Dim broker As JObject = DirectCast(brokers(i), JObject) 
          Dim brokerId As Integer = broker("broker_id").Value(Of Integer) 
          Dim name As String = broker("name").Value(Of String) 
          Dim email As String = broker("emailaddress").Value(Of String) 
          Console.WriteLine("broker " & i.ToString() & " id: " & brokerId) 
          Console.WriteLine("broker " & i.ToString() & " name: " & name) 
          Console.WriteLine("broker " & i.ToString() & " email: " & email) 
         Next 
        End If 
    

    마찬가지로, 당신은 같은 것을 할 필요가있을 것이다

      Dim email As String = "" 
          If broker("emailaddress") IsNot Nothing Then 
           email = broker("emailaddress").Value(Of String) 
          End If 
    

    실제로 JSON에 항상 존재할 수없는 많은 속성이 있다는 것을 알게되면 약간의 확장 메서드를 작성하여 코드를 단순화 할 수 있습니다.

    Imports System.Runtime.CompilerServices 
    Imports Newtonsoft.Json.Linq 
    
    Module JsonExtensions 
    
        <Extension()> 
        Public Function ValueOrDefault(Of T)(token As JToken, defaultValue As T) As T 
         If token IsNot Nothing AndAlso token.Type <> JTokenType.Null Then 
          Return token.Value(Of T) 
         Else 
          Return defaultValue 
         End If 
        End Function 
    
    End Module 
    

    그럼 당신은 당신이 현재에 Value(Of T) 또는 DirectCast을 사용하는 곳에서 사용할 수 있습니다 : 그것은 Nothing이 밝혀 경우 디폴트 값을 제공 할 수 있도록이 방법은 특정 JToken의 장소에 사용되는 JToken.

    Dim brokers As JArray = item("broker").ValueOrDefault(new JArray()) 
    

    또는 :

    Dim email As String = broker("emailaddress").ValueOrDefault("") 
    
    +0

    감사 예를 들어! 당신은'photos' 배열에 대해 작동하지만'broker' 속성에 에러를 던집니다 (업데이트 2 참조) ... 왜 그 이유를 설명 할 수 있습니까? – Flo

    +1

    @Flo - 귀하의 질문에있는 예제가 "실제"JSON의 단축 버전 일 뿐이라고 생각하십니까? 게시 한 업데이트 된 예제에서는 오류를 가져올 이유가 없습니다. '브로커 (broker) '는 길이 1 배열입니다. 그러나 더 길고 다른 JSON에 대해이 코드를 실행하고 JSON이 각 결과 항목에 대해 항상 '브로커'를 갖고있는 것은 아니라면 오류가 표시됩니다. 나는 당신이 그것을 고칠 수있는 방법을 설명하기 위해 나의 대답을 업데이트했다. –

    +0

    당신은 옳았습니다 ... 신인의 실수이지만, 뜻밖의 발견 : 저는 정말 멋진 확장 방법을 가지고 있습니다 :-). 그것에 대한 한 가지 질문 : 내 JSON' "title": null'에이 내용이 있습니다. 확장 메소드 인'name = item ("title") .ValueOrDefault ("")'를 사용할 때 변수'name'은 빈 문자열 대신에'Nothing'이되므로 코드는 여전히 실패합니다. 어떻게 해결할 수있는 확장 프로그램을 변경할 수 있습니까? – Flo