2012-10-31 25 views
5

Tôi hiện đang cố gắng sử dụng Flexjson để deserialize một chuỗi JSON và ánh xạ nó vào mô hình Object của ứng dụng Android của tôi. Ứng dụng này là một loại thư viện với một số nhà cung cấp có thể có một số danh mục có nhiều catalog hơn và các tài liệu trong đó. Các json được lấy từ một dịch vụ web tôi không có ảnh hưởng trên và trông giống như sau:Ánh xạ một JSONObject vào một Danh sách với Flexjson trong Java/Android

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

Vì vậy, mỗi nhà cung cấp, danh mục, tài liệu được đại diện bởi một JSONObject và tất cả các catalog con và các văn bản nằm trong một JSONArray. Cho đến nay mọi thứ hoạt động tốt với Flexjson và mã deserialization sau:

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

tôi có một đối tượng thư viện mà có một List<Vendor>. Mỗi nhà cung cấp có List<Catalog>List<Document>.

Nhưng thật không may, dịch vụ web khóa JSONArrays thành JSONObject đơn giản nếu một danh mục chỉ chứa một tài liệu hoặc danh mục chỉ chứa một danh mục. Vì vậy, các json trong trường hợp đó trông như thế này:

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

Bây giờ Flexjson không biết làm thế nào để deserialize và tôi kết thúc với một library.vendorX.getDocument() là một List<HashMap> thay vì một List<Document>. Một ý tưởng là nói cho Flexjson một cách rõ ràng cách xử lý các trường hợp như vậy, nhưng tôi không biết bắt đầu từ đâu. Một cách khác có thể là phân tích cú pháp json ban đầu theo cách thủ công và thay thế các JSONObject đó bằng JSONArray thích hợp. Nhưng tôi nghĩ rằng cách đó không thực sự tốt đẹp để đi, vì thư viện có thể khá sâu.

Tôi hy vọng bạn có thể cung cấp một số hướng dẫn tại đây.

Trả lời

1

Yikes đây là một số bản đồ json gnarly đang diễn ra. Gì coder phụ trợ đã làm điều đó ?! #NotHelping.

Cũng từ việc xem mã, Flexjson được mã hóa để xử lý việc này ra khỏi hộp. Nhưng có vẻ như nó không truyền thông tin đánh máy xuống đến ràng buộc, vì vậy nó không biết loại nào nó liên kết với nhau nên nó chỉ trả về một Bản đồ. Đó là lỗi có thể sẽ được khắc phục. Tin tốt là có một tác phẩm xung quanh.

Dù sao, điều đơn giản nhất tôi có thể nghĩ đến là cài đặt ObjectFactory trên danh sách đó. Sau đó, bạn có thể kiểm tra và xem liệu bạn có Bản đồ hoặc Danh sách khi luồng không được deserialized. Sau đó, bạn có thể bọc nó trong một Danh sách và gửi nó đến bộ giải mã thích hợp. Một cái gì đó như:

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

Sau đó

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; 
      } 
     } 
    } 
} 

Tôi nghĩ đó là khoảng những gì sẽ khắc phục lỗi đó, nhưng cũng nên khắc phục vấn đề của bạn.

+0

Cảm ơn câu trả lời của bạn! Tôi nghĩ rằng tôi làm cho bản thân mình không rõ ràng, tôi luôn luôn có được một danh sách nhưng trong trường hợp chỉ có một tài liệu tôi không có 'tài liệu' trong danh sách nhưng' HashMaps', do đó, 'Danh sách ' như 'catalog.document' thay vì 'Danh sách '. Các đối tượng bản đồ băm chứa dữ liệu được kết nối với tài liệu. Có vẻ lạ với tôi. Tôi nghĩ rằng tôi cần một nhà máy mà quyết định nếu chúng tôi đã có một tài liệu hoặc nếu chúng tôi có một 'HashMap'. Nếu sau này tôi sẽ ánh xạ đối tượng tài liệu theo cách thủ công.Nỗ lực đầu tiên của tôi thất bại. Bạn có nghĩ rằng cách tiếp cận này là có thể? –

+0

Tôi không thấy câu trả lời của tôi không giải đáp được vấn đề của bạn. Tôi nghĩ lý do bạn đang nhận được Danh sách thay vì Danh sách là lỗi trong Flexjson. JSONDeserializer đầu tiên dịch JSON thành các đối tượng đơn giản như List, Map, String, Number, và Boolean. Sau đó, nó sử dụng một loạt các ObjectFactory để ánh xạ các đối tượng đơn giản đó vào các đối tượng thực tế mà bạn đang ánh xạ vào. Vì vậy, lớp ObjectFactory là trước khi chúng ta có một đối tượng được đánh máy mạnh như Document. Vì vậy, bạn sẽ cắm vào điểm đó bằng cách viết ObjectFactory của riêng bạn như tôi đã cho thấy thay vì sử dụng cá thể mặc định. – chubbsondubs

+0

Tôi xin lỗi, tôi nghĩ tôi đã hiểu lầm bạn ở đó. Dù sao, khi cố gắng bạn mã tôi nhận được một ngoại lệ tại 'ParameterizedType ptype = (ParameterizedType) targetType;' 'java.lang.ClassCastException: java.lang.Class không thể được đưa vào java.lang.reflect.ParameterizedType'. Một câu hỏi khác: Nếu tôi chỉ định Nhà máy được sử dụng trên 'library.vendor.values.catalog.values.document', nó sẽ không ảnh hưởng đến các cấp độ khác như' library.vendor.values.document'? Ngay cả khi một nhà cung cấp có thể có tài liệu ... Có thể chỉ định nhà máy được sử dụng trên 'LibraryItem.class' là lớp bậc trên của tất cả những người khác không? –

Các vấn đề liên quan