2013-08-23 5 views
1

처음으로 JSON을 처리하고 OpenTSDB에서 데이터를 가져옵니다. JSON을 deserialize하기 위해 C# 클래스를 만들었지 만, 오류가 발생했습니다. '현재 JSON 배열을 deserialize 할 수 없습니다' 아래 설명 된대로.JSON 객체가 C# 객체로 deserialize됩니다. - OpenTSDB

내 C# 코드를 얻을 수 JSON :

var request = WebRequest.Create("http://localhost:4242/api/query?start=2013/08/21-12:00:00&end=2013/08/22-12:00:00&m=sum:tcollector.collector.lines_sent&o=&yrange=%5B0:%5D&wxh=924x773"); 
     request.ContentType = "application/json; charset=utf-8"; 
     string text; 
     try 
     { 
      var response = (HttpWebResponse) request.GetResponse(); 
      using (var sr = new StreamReader(response.GetResponseStream())) 
      { 
       text = sr.ReadToEnd(); 
      } 

      uxResponse.Text = text; 

      OpenTSDBResponse myObject = (OpenTSDBResponse)Newtonsoft.Json.JsonConvert.DeserializeObject(text, typeof(OpenTSDBResponse)); 

      var variable = Newtonsoft.Json.JsonConvert.DeserializeObject(text); 

      //var tester = myObject; 
     } 
     catch (Exception ex) 
     { 
      uxResponse.Text = GetFullExceptionMessage(ex); 
     } 

나는 위의 코드에서 수신 오전 JSON (즉, '텍스트'변수) :

[{ 
"metric":"tcollector.collector.lines_sent", 
"tags": 
    { 
    "host":"ubuntu1" 
    }, 
"aggregateTags":["collector"], 
"dps": 
    { 
    "1377050434":1271779.0, 
    "1377050494":1272073.0, 
    "1377050554":1272502.0, 
    "1377050614":1273632.0, 
    "1377050674":1273867.0 
    } 
}] 

내 C# 클래스

internal class OpenTSDBResponse 
    { 
     [JsonProperty("metric")] 
     public string Metric { get; set; } 

     [JsonProperty("tags")] 
     public Tags Tags { get; set; } 

     [JsonProperty("aggregateTags")] 
     public string[] AggregateTags { get; set; } 

     [JsonProperty("dps")] 
     public List<TimeValue> TimeValues { get; set; } 
    } 

internal class Tags 
{ 

    [JsonProperty("host")] 
    public string Host { get; set; } 
} 

internal class TimeValue 
{ 
    [JsonProperty("Time")] 
    public double Time { get; set; } 

    [JsonProperty("Value")] 
    public double Value { get; set; } 
} 
,

오류 역 직렬화하는 개체 :

현재 JSON 배열을 직렬화 할 수 없다 (예를 들어 JSON 개체 (예 : { "name": "value"})가 올바르게 직렬화를 필요로하기 때문에 유형을 'MyNamespace.OpenTSDBResponse'로 변경하십시오.이 문제를 해결하려면 JSON을 JSON 객체에서 (예 : { "name": "value"}) 또는 deserialized 유형을 배열 또는 을 구현하는 유형으로 변경합니다. List와 같은 컬렉션 인터페이스 (예 : ICollection, IList)는 을 JSON 배열에서 직렬화 해제 할 수 있습니다. . JsonArrayAttribute 또한 내가 CodeProject의 직렬화 해 JSON 사용

JSON array.Path ', 라인 1 위치 1

추가 정보로부터 직렬화하도록 강제하는 형태로 첨가 될 수있다 프로젝트를 만들어 기본 클래스를 만들었지 만 각 "1377050434": 1271779.0에 대한 새 C# 속성을 만들었으므로 TimeValue 클래스를 사용하도록 업데이트했습니다. http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-C

질문 :

어떻게이 적절한 C# 클래스 구조로받을 수 있나요? 아래 사용자의 의견에 응답

추가 정보 :

  • bjaminn의 코멘트 : 당신이 받고있는 JSON 배열 믿습니다. 예외는 실제로 OpenTSDBResponse []가 필요할 때 객체 []를 OpenTSDBResponse로 변환한다고 말하려고합니다. 이것을 디버깅하는 또 다른 방법은 변수 변수를보고 디버거에 어떤 유형이 있는지 확인하는 것입니다. 물론 예외를 던진 줄은 주석 처리되어야합니다.

    결과

    : 제가

    OpenTSDBResponse [] 인 myObject = (OpenTSDBResponse []) Newtonsoft.Json.JsonConvert처럼 직렬화 변성.DeserializeObject (text, typeof (OpenTSDBResponse []));

    현재 JSON 객체를 직렬화 할 수 없습니다 (예 : { "이름": "값"}) 타입으로 'System.Collections.Generic.List`1 내가 그것을 실행했을 때

    하지만

    다음과 같은 오류가 발생했습니다 [MyNamespace.OpenTSDBResponseJsonTypes.TimeValue] '유형에 JSON 배열 (예 : [1,2,3])이 필요합니다.이 오류를 수정하려면 JSON 배열 (예 : [1,2,3] JSON 객체에서 직렬화 해제 할 수있는 일반 .NET 유형 (예 : 정수와 같은 기본 유형이 아니고 배열이나 List와 같은 콜렉션 유형이 아닌)이되도록 직렬화 해제 유형을 변경하십시오. JsonObjectAttribute 또한 JSON object.Path '[0] .dps.1377050434'선 1 위치 작업 용액에 121

추가 정보로부터 직렬화하도록 강제하는 형태로 첨가 될 수있다 JSON을 처음 사용하는 경우 "유닉스 타임 스탬프 데이터", "값"이므로 사전에 대한 클래스에 다른 속성을 추가했습니다. 이를 통해 C#에서 datetime/value를 사용하여 작업 할 수 있습니다. 전송을위한 더 나은 방법이있을 수 있지만이 시나리오는 별다른 성능 문제를 일으키지 않습니다.

[JsonProperty("dps")] 
    public Dictionary<string, double> TimeValues { get; set; } 

    public List<TimeValue> DataPoints 
    { 
     get 
     { 
      List<TimeValue> times = new List<TimeValue>(); 
      DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0); 

      foreach (var item in TimeValues) 
      { 
       times.Add(new TimeValue 
       { 
        Time = dtDateTime.AddSeconds(double.Parse(item.Key)).ToLocalTime(), 
        Value = item.Value 
       }); 
      } 

      return times; 
     } 
    } 

답변

1

내가받는 JSON이 배열이라고 생각합니다. 예외는 당신이 정말로 원할 때 객체 []OpenTSDBResponse으로 변환하려고한다고 말합니다. OpenTSDBResponse [].

이것을 디버깅하는 또 다른 방법은 변수 변수을보고 디버거에 어떤 유형이 있는지 확인하는 것입니다. 물론 예외를 던진 줄은 주석 처리되어야합니다.

새로운 오류 태클 DPS가 적절한 JSON 배열이 아닌 것 같습니다. JSON 호출마다 키가 다른 것처럼 보이므로 사전에 구문 분석 할 수 있습니다.

JSON convert dictionary to a list of key value pairs

새로운 클래스 : 나는 당신의 제안을 시도한 후

internal class OpenTSDBResponse 
    { 
     [JsonProperty("metric")] 
     public string Metric { get; set; } 

     [JsonProperty("tags")] 
     public Tags Tags { get; set; } 

     [JsonProperty("aggregateTags")] 
     public string[] AggregateTags { get; set; } 

     [JsonProperty("dps")] 
     public Dictionary<string,double> TimeValues { get; set; } 
    } 
+0

나는 내 질문에 업데이트되었습니다. 다른 오류, 예상대로 코드를 수정 했습니까? 감사. – John

+0

업데이트 된 예제를 사용해 주셔서 감사합니다. 사전 이 나를 위해 이것을 분류했습니다. – John

+0

사전 이 문자열을 유닉스 날짜로 사용하므로 사전 으로 캐스팅 할 수 있습니까? – John

0
You can such so modify your Json Data and your C# Code,for example 
    [{ 
    "metric":"tcollector.collector.lines_sent", 
    "tags": 
    { 
    "host":"ubuntu1" 
    }, 
    "aggregateTags":["collector"], 
    "dps": 
    [ 
    {"Time":"1377050434","Value":1271779.0}, 
    {"Time":"1377050554","Value":1272502.0}   
    ] 
    }] 
c# Code:   
You provide the data is an Array,so when you deserialize the string,you must such so use generic format of deserializeobject 

    object obj=Newtonsoft.Json.JsonConvert.DeserializeObject<List<OpenTSDBResponse>>(json.ToString()); 
+0

JSON을 수정할 수 있다고 생각하지 않습니다. 표준 형식의 OpenTSDB에서 가져온 것이라고 생각합니다. – John