2011-03-07 7 views
34

JSON.NET 라이브러리를 사용하여 Facebook에서 반환 된 데이터를 비 직렬화하는 데 문제가 있습니다.때로는 배열 및 때로는 객체 일 때 JSON deserializing

"attachment":{ 
     "media":[ 
      { 
       "href":"http://www.facebook.com/photo.php?fbid=12345", 
       "alt":"", 
       "type":"photo", 
       "src":"http://photos-b.ak.fbcdn.net/hphotos-ak-ash1/12345_s.jpg", 
       "photo":{"aid":"1234","pid":"1234","fbid":"1234","owner":"1234","index":"12","width":"720","height":"482"}} 
     ], 

모든 것이 잘 작동하고 난 아무 문제가 없습니다 :

{ 
    "attachment":{"description":""}, 
    "permalink":"http://www.facebook.com/permalink.php?story_fbid=123456789" 
} 

은 JSON이 같은 사진이 보이는 반환 : 같은

는 JSON은 단순한 벽 게시물에서 반환 보인다. 이제 다음 JSON과 모바일 클라이언트에서 간단한 벽 포스트 건너는데, 직렬화 이제이 하나의 게시물 실패

public class FacebookAttachment 
    { 
     public string Name { get; set; } 
     public string Description { get; set; } 
     public string Href { get; set; } 
     public FacebookPostType Fb_Object_Type { get; set; } 
     public string Fb_Object_Id { get; set; } 

     [JsonConverter(typeof(FacebookMediaJsonConverter))] 
     public List<FacebookMedia> { get; set; } 

     public string Permalink { get; set; } 
    } 
: 여기
"attachment": 
    { 
     "media":{}, 
     "name":"", 
     "caption":"", 
     "description":"", 
     "properties":{}, 
     "icon":"http://www.facebook.com/images/icons/mobile_app.gif", 
     "fb_object_type":"" 
    }, 
"permalink":"http://www.facebook.com/1234" 

내가 같이 직렬화 복원하고있는 클래스입니다

FacebookMediaJsonConverter를 사용하지 않으면 오류가 발생합니다. JSON 객체를 'System.Collections.Generic.List`1 [FacebookMedia]'유형으로 비 직렬화 할 수 없습니다. JSON에서는 미디어가 컬렉션이 아니기 때문에 의미가 있습니다.

나는 비슷한 문제를 설명하는이 게시물을 발견, 그래서 나는이 경로를 아래로 이동을 시도했습니다 : I를 제외하고 잘 작동

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
    if (reader.TokenType == JsonToken.StartArray) 
      return serializer.Deserialize<List<FacebookMedia>>(reader); 
    else 
      return null; 
} 

지금 얻을 : 같은 Deserialize JSON, sometimes value is an array, sometimes "" (blank string)

내 컨버터 보인다 새로운 예외 :

내부 JsonSerializerInternalReader.cs, CreateValueInternal() : 예기치 않은 토큰 역 직렬화하는 동안 개체 : PROPERTYNAME

reader.Value의 값은 "permalink"입니다. 스위치에서 JsonToken.PropertyName의 경우가없는 것을 분명히 볼 수 있습니다.

내가 변환기에서 다르게해야 할 일이 있습니까? 어떤 도움을 주셔서 감사합니다.

답변

20

데 도움이되는 솔루션입니다 : 그것은 JSON 객체 때 문제는, 내가 속성을지나 읽고 있지 하였다

. 올바른 코드는 다음과 같습니다.

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
    if (reader.TokenType == JsonToken.StartArray) 
    { 
     return serializer.Deserialize<List<FacebookMedia>>(reader); 
    } 
    else 
    { 
     FacebookMedia media = serializer.Deserialize<FacebookMedia>(reader); 
     return new List<FacebookMedia>(new[] {media}); 
    } 
} 

James는 위의 방법에 대한 단위 테스트를 제공하기에 충분히 친절했습니다.

2

C# 프레임 워크의 System.Runtime.Serialization 네임 스페이스를 살펴보면 매우 빠르게 원하는 위치로 이동할 수 있습니다. 당신이 원하는 경우

, 당신은 this 프로젝트 (내 자신의 작품을 연결하기 위해 노력하지 않고 몇 가지 예제 코드를 체크 아웃 할 수 있지만, 난 그냥 꽤 당신이하고 정확히 많이하지만 다른 소스 API를 완료.

이 희망 .. 여기 JSON.NET의 개발자는 프로젝트 CodePlex의 사이트에 도움이 결국

+1

-1 코드 샘플에 대한 링크가있는 제 3 자 라이브러리를 통해 프레임 워크의 내부 입증 된 부분을 사용하기위한 권장 사항은 무엇입니까? – jonezy

+0

매우 드문 것처럼 보입니다. – jonezy

+0

-1이 어디서 왔는지 확실하지 않습니다. 나는 그 반응에 감사한다. 아마 그것이 사소한 문제 (아마도 JSON.NET의 오용으로 인한 것일 수도 있습니다)에 대한 상당히 중량 솔루션 인 것 같습니다. 그 말은, 나는 Systme.Runtime.Serialization 메서드를 시도하고 더 나은 결과가 끝나면 참조하십시오. 링크를 가져 주셔서 감사합니다. – mfanto

-2

나는이 수업을 다음과 같이 작성해야한다고 생각합니다. !!!

public class FacebookAttachment 
    { 

     [JsonProperty("attachment")] 
     public Attachment Attachment { get; set; } 

     [JsonProperty("permalink")] 
     public string Permalink { get; set; } 
    } 

public class Attachment 
    { 

     [JsonProperty("media")] 
     public Media Media { get; set; } 

     [JsonProperty("name")] 
     public string Name { get; set; } 

     [JsonProperty("caption")] 
     public string Caption { get; set; } 

     [JsonProperty("description")] 
     public string Description { get; set; } 

     [JsonProperty("properties")] 
     public Properties Properties { get; set; } 

     [JsonProperty("icon")] 
     public string Icon { get; set; } 

     [JsonProperty("fb_object_type")] 
     public string FbObjectType { get; set; } 
    } 
public class Media 
    { 
    } 
public class Properties 
    { 
    } 
19

이 사례를 처리하는 방법에 대한 자세한 설명은 "Using a Custom JsonConverter to fix bad JSON results"입니다.

은 당신의 원하는 유형의 목록을 반환하는 컨버터를 확장하면 문제

[JsonConverter(typeof(SingleValueArrayConverter<OrderItem>))] 
public List<OrderItem> items; 
    1. 주석 속성을하고있는 기본 JSON.NET 컨버터를 확장 할 수 있습니다, 요약하면 단일 개체의 경우

      public class SingleValueArrayConverter<T> : JsonConverter 
      { 
          public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
          { 
           throw new NotImplementedException(); 
          } 
      
          public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
          { 
           object retVal = new Object(); 
           if (reader.TokenType == JsonToken.StartObject) 
           { 
            T instance = (T)serializer.Deserialize(reader, typeof(T)); 
            retVal = new List<T>() { instance }; 
           } else if (reader.TokenType == JsonToken.StartArray) { 
            retVal = serializer.Deserialize(reader, objectType); 
           } 
           return retVal; 
          } 
      
          public override bool CanConvert(Type objectType) 
          { 
           return true; 
          } 
      } 
      

    기사에서 언급했듯이이 확장은 완전히 일반적인 것은 아니지만 목록을 얻는 것이 좋습니다.

  • +0

    절대적으로 좋습니다. 고맙습니다. – NotMe

    +0

    혼란 스럽군요 - WriteJson이 구현되지 않고 던지고 있습니까? 이걸 처리해야합니까? – nologo