2013-02-25 80 views
7

我试图反序列化(使用GSON)JSON对象,看起来像这样一个JSON对象:反序列化,内带多个项目

 "attachments": { 
      "40": { 
       "ID": 40, 
       "URL": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/wreckit.jpg", 
       "guid": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/wreckit.jpg", 
       "mime_type": "image\/jpeg", 
       "width": 287, 
       "height": 400 
      }, 
      "3": { 
       "ID": 3, 
       "URL": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/frankenweenie2bposter.jpg", 
       "guid": "http:\/\/drewmore4.files.wordpress.com\/2013\/02\/frankenweenie2bposter.jpg", 
       "mime_type": "image\/jpeg", 
       "width": 273, 
       "height": 400 
      } 
    }, 

我该如何处理呢?我甚至不知道该怎么称呼这个 - 这里有多个“项目”,但它不是一个数组。当我尝试将它反序列化为一个数组时,程序崩溃在“预期的Begin_Array上但发现了Begin_Object”异常。当我尝试将它反序列化为一个Strong对象(请参见下面的类)时,程序将运行,但所有字段都返回null。

这里是我试图把它映射到类:

class Attachment { 
int ID; 
String URL; 
} 

完整JSON文件可以看出here:

编辑:解决。

@ Perception的解决方案基本上可行。这个“元素”(仍然想知道这个多项/非数组json元素)嵌入到一个包含数组的更大的json对象中是很复杂的。再一次,这个JSON不是我的设计 - 它来自Wordpress REST API,并且(就像@Perception暗示的那样),我想我遇到的问题说明了它的一个设计缺陷 - 即附件元素应该是一个数组而不是单个对象。尽管如此,

但是,如果其他人永远需要使用此API反序列化对一个站点的所有职位查询的结果,并进一步需要访问附件上的每个岗位,这里是你如何做到这一点:

private class getAll extends AsyncTask <Void, Void, JSONObject> { 
    private static final String url = "https://public-api.wordpress.com/rest/v1/sites/drewmore4.wordpress.com/posts/"; 
    @Override 
    protected JSONObject doInBackground(Void... params) { 

     HttpClient httpclient = new DefaultHttpClient(); 
     HttpGet httpget = new HttpGet(url); 
     httpget.addHeader("accept", "application/json"); 
     JSONObject returned = new JSONObject(); 
     HttpResponse response; 

     try { 
      response = httpclient.execute(httpget); 
      HttpEntity entity = response.getEntity(); 

      if (entity != null) { 
       InputStream instream = entity.getContent(); 
       String result= convertStreamToString(instream); 

       returned =new JSONObject(result);     
       instream.close(); 
      } 
     } 
     catch (ClientProtocolException | IOException | JSONException e) { e.printStackTrace();} 

     return returned; 
    } 

     @Override 
    protected void onPostExecute (JSONObject returned){ 
     Gson gson = new Gson(); 

//posts is the element within the JSONObject that is an array of post objects 
     try { 
     JSONArray posts = returned.getJSONArray("posts"); 

     for (int curr = 0; curr < posts.length(); curr++){ 
      String s = posts.get(curr).toString(); 

      Article a = gson.fromJson(s, Article.class); 

      JSONObject attachments = new JSONObject(s).getJSONObject("attachments"); 
      final Iterator<String> keys = attachments.keys(); 
       while(keys.hasNext()) { 
        final String key = keys.next(); 
        a.attached.add(gson.fromJson(attachments.getJSONObject(key).toString(), Attachment.class)); 
       } 
       stories.add(a); 
     } 

      } catch (JSONException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

回答

7

这是可能应该已被序列化为一个数组,但没有数据的一个例子。解析它的一个解决方案是直接使用JSONObject

String json = ...; 
final Gson gson = new Gson(); 

final List<Attachment> attachements = new ArrayList<Attachment>(64); 
final JSONObject jsonObj = new JSONObject(json).getJSONObject("attachments"); 
final Iterator<String> keys = jsonObj.keys(); 
while(keys.hasNext()) { 
    final String key = keys.next(); 
    attachements.add(gson.fromJson(jsonObj.getJSONObject(key).toString(), Attachment.class); 
} 

// Do something with attachements 

数据可以也被看作是一个图,ID的对附件。它可以反序列化,例如:

final String jsonObj = new JSONObject(json).getJSONObject("attachments"); 
final Gson gson = new Gson(); 
final Map<String, Attachment> data = gson.fromJson(jsonObj.toString(), 
     new TypeToken<Map<String, Attachment>>() { 
     }.getType()); 
final List<Attachment> attachments = new ArrayList<Attachment>(data.values()); 

这是实际工作

+0

我认为这里有一个误解,无论是我的还是你的。这里呈现的内容不是文章,而是文章的组件(即附件),我试图反序列化到您以前帮助过的文章实例的字段中。 – drewmoore 2013-02-25 05:43:12

+0

@ drewmore4 - 确实如此。看看我的编辑(没有任何实质性的,基本上用'Attachment'替换'Article')。 – Perception 2013-02-25 05:53:14

+0

这就是我想的:)我试着你的建议,但得到一个错误警告 - 只能遍历一个数组或java.lang.Iterable的实例 - for循环。 – drewmoore 2013-02-25 06:05:15

2

首先从这个JSONObject的创建JSONArray, 然后

for(int i = 0; i < contacts.length(); i++){ 
      JSONObject c = contacts.getJSONObject(i); 

通过使用这种循环得到字符串值,放在一个地图或对象ü希望并将其添加到一个ArrayList中

HashMap<String, String> map = new HashMap<String, String>(); 

      // adding each child node to HashMap key => value 
      map.put(TAG_ID, id); 

而且

contactList.add(map); 

,那么你可以使用该值。

0

我该如何处理呢?我甚至不知道该怎么称呼这个 - 这里有多个“项目”,但它不是一个数组。

它看起来像JSON中的集合是天生适合java.util.map。所以,我可能会将JSON“附件”反序列化为Map<String, Atachment>。然后,地图很容易迭代,或将附件值集合转换为不同类型的集合,如List<Attachment>Attachment[]

注意:The Gson User Guide包括反序列化到通用集合的示例。