2012-10-31 2 views
5

현재 Flexjson을 사용하여 JSON 문자열을 비 직렬화하고이를 내 Android App의 객체 모델에 매핑하려고합니다. 이 응용 프로그램은 더 많은 카탈로그가있는 카탈로그를 가질 수있는 여러 공급 업체의 라이브러리 종류입니다 ( ). json으로 내가에 영향을 미치지 않는 웹 서비스에서 가져온이며,이 같은 외모 : 그래서, 카탈로그, 문서가 된 JSONObject 및 모든 하위 목록을 문서로 각 벤더 표현된다 Java/Android에서 Flexjson을 사용하여 JSONObject를 목록에 매핑하는 중

{ 
    "library":{ 
     "vendor":[ 
      { 
       "id":146, 
       "title":"Vendor1", 
       "catalog":[ 
        { 
         "id":847, 
         "document":[ 
          { 
           "id":1628, 
           "title":"Document", 
       ... 
          }, 
          { 
       ... 
          } 
         ], 
         "title":"Catalog ", 
        }, 
       { 
       ... 
       } 
       ] 
      }, 
      { 
      ... 
      } 
     ] 
    } 
} 

은 JSONArray 내에 있습니다. 지금까지 모든 Flexjson 다음과 같은 직렬화 코드와 잘 작동 :

LibraryResponse response = new JSONDeserializer<LibraryResponse>() 
        .use(Timestamp.class, new TimestampObjectFactory()) 
        .deserialize(getLocalLibrary(), LibraryResponse.class); 
return response.library; 

나는 List<Vendor>이있는 라이브러리 개체가 않습니다. 각 공급 업체는 List<Catalog>List<Document>입니다.

그러나 불행하게도 카탈로그에 단일 문서 만 있거나 카탈로그에 단 하나의 카탈로그 만 있으면 JSONArrays에 간단한 JSONObjects가 적용됩니다. 그래서 경우에 JSON은 다음과 같습니다 대신 List<Document>List<HashMap> 인)

"document": 
    { 
     "id":1628, 
     "title":"Document", 
     ... 
    } 

이제 Flexjson 어떻게 직렬화하는 방법을 알고하지 않습니다와 나는 library.vendorX.getDocument (와 끝까지. 하나의 아이디어는 Flexjson에게 이러한 케이스를 처리하는 방법을 명시 적으로 알려주는 것이지만 어디서부터 시작해야할지 모르겠습니다. 또 다른 방법은 초기 json을 수동으로 구문 분석하고 해당 JSONObject를 적절한 JSONArray로 바꾸는 것입니다. 그러나 도서관이 꽤 깊을 수 있기 때문에 그렇게가는 것이 좋지 않다고 생각합니다.

여기에 몇 가지 안내를 제공해 주시면 감사하겠습니다.

답변

1

Yikes 이것은 약간의 험난한 json 매핑입니다. 무슨 백엔드 코더가 그랬어?! # 아니요.

코드를 살펴 보니 Flexjson은이 상자를 처리하기 위해 코드화되어 있습니다. 그러나 바인딩 정보를 타이핑 정보에 전달하지 않는 것처럼 보이기 때문에 어떤 타입의 바인딩인지 알지 못하기 때문에 단지 맵을 리턴합니다. 아마도 버그이 수정되어야합니다. 희소식은의 주위에 일이있다.

어쨌든 가장 간단한 생각은 ObjectFactory을 해당 목록에 설치하는 것입니다. 그런 다음 스트림이 deserialize 될 때 Map 또는 List가 있는지 확인하고 확인할 수 있습니다. 그런 다음 목록에 랩핑하여 적절한 디코더로 보낼 수 있습니다. 같은 뭔가 :

LibraryResponse response = new JSONDeserializer<LibraryResponse>() 
       .use(Timestamp.class, new TimestampObjectFactory()) 
       .use("library.vendor.values.catalog.values.document", new ListDocumentFactory()) 
       .deserialize(getLocalLibrary(), LibraryResponse.class); 

그런 다음
public class ListDocumentFactory implements ObjectFactory { 

    public Object instantiate(ObjectBinder context, Object value, Type targetType, Class targetClass) { 
     if(value instanceof Collection) { 
      return context.bindIntoCollection((Collection)value, new ArrayList(), targetType); 
     } else { 
      List collection = new ArrayList(); 
      if(targetType instanceof ParameterizedType) { 
       ParameterizedType ptype = (ParameterizedType) targetType; 
       collection.add(context.bind(value, ptype.getActualTypeArguments()[0])); 
      } else { 
       collection.add(context.bind(value)); 
       return collection; 
      } 
     } 
    } 
} 

내가 그 그 버그를 해결하는 것뿐만 아니라, 문제를 해결해야하는지 대략 생각합니다.

+0

답변 해 주셔서 감사합니다. 나는 내가 명확히하지 않았다고 생각한다, 나는 항상 List를 얻는다. 그러나 단 하나의 문서 만있는 경우 List에'Documents'가 없지만'HashMaps'가 있으므로 List를'catalog.document' 대신에'List ' 'List '. 해시 맵 객체에는 문서에 연결된 데이터가 포함됩니다. 나에게 이상하게 보입니다. 우리가 이미 Document를 가지고 있는지 또는 HashMap을 가지고 있는지를 결정하는 Factory가 필요하다고 생각합니다. 후자의 경우 수동으로 문서 객체를 매핑합니다.그래도 첫 번째 시도는 실패했습니다. 이 접근법이 가능하다고 생각하십니까? –

+0

내 대답이 당신의 문제에 어떻게 대답하지 못했는지 알지 못합니다. 목록 대신 목록 이 나오는 이유는 Flexjson의 버그입니다. JSONDeserializer는 먼저 List, Map, String, Number 및 Boolean과 같은 간단한 객체로 JSON을 변환합니다. 그런 다음 일련의 ObjectFactory를 사용하여 이러한 간단한 객체를 매핑하려는 실제 객체에 매핑합니다. 그래서 ObjectFactory 레이어는 Document와 같은 강력한 타입의 객체를 갖기 전에 존재합니다. 따라서 기본 인스턴스를 사용하는 대신 보여준 것처럼 자신 만의 ObjectFactory를 작성하여이 지점에 연결합니다. – chubbsondubs

+0

죄송합니다. 오해 하셨을 것입니다. 어쨌든, 내가'ParameterizedType ptype = (ParameterizedType) targetType;에서 예외를 얻고있다. java.lang.ClassCastException : java.lang.Class를 java.lang.reflect.ParameterizedType'으로 형변환 할 수 없다. 또 다른 질문 :'library.vendor.values.catalog.values.document'에서 사용할 팩토리를 지정하면'library.vendor.values.document'라는 다른 레벨에는 영향을 미치지 않을까요? 납품업자조차도 문서를 가질 수 있습니다 ... 다른 모든 클래스의 수퍼 클래스 인'LibraryItem.class'에서 사용할 팩토리를 지정할 수 있습니까? –