如何用 Gson 解析 JSON 数组

我想解析 JSON 数组并使用 gson。首先,我可以记录 JSON 输出,服务器正在清晰地响应客户端。

下面是我的 JSON 输出:

 [
{
id : '1',
title: 'sample title',
....
},
{
id : '2',
title: 'sample title',
....
},
...
]

我尝试使用这种结构来解析.A 类,它依赖于单个 arrayArrayList来解析所有 JSONArray。

 public class PostEntity {


private ArrayList<Post> postList = new ArrayList<Post>();


public List<Post> getPostList() {
return postList;
}


public void setPostList(List<Post> postList) {
this.postList = (ArrayList<Post>)postList;
}
}

班级:

 public class Post {


private String id;
private String title;


/* getters & setters */
}

当我尝试使用 gson 时,没有错误,没有警告,也没有日志:

 GsonBuilder gsonb = new GsonBuilder();
Gson gson = gsonb.create();


PostEntity postEnt;
JSONObject jsonObj = new JSONObject(jsonOutput);
postEnt = gson.fromJson(jsonObj.toString(), PostEntity.class);


Log.d("postLog", postEnt.getPostList().get(0).getId());

怎么了,我怎么解决?

141236 次浏览

You can parse the JSONArray directly, don't need to wrap your Post class with PostEntity one more time and don't need new JSONObject().toString() either:

Gson gson = new Gson();
String jsonOutput = "Your JSON String";
Type listType = new TypeToken<List<Post>>(){}.getType();
List<Post> posts = gson.fromJson(jsonOutput, listType);

Hope that helps.

I was looking for a way to parse object arrays in a more generic way; here is my contribution:

CollectionDeserializer.java:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;


import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;


public class CollectionDeserializer implements JsonDeserializer<Collection<?>> {


@Override
public Collection<?> deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
Type realType = ((ParameterizedType)typeOfT).getActualTypeArguments()[0];


return parseAsArrayList(json, realType);
}


/**
* @param serializedData
* @param type
* @return
*/
@SuppressWarnings("unchecked")
public <T> ArrayList<T> parseAsArrayList(JsonElement json, T type) {
ArrayList<T> newArray = new ArrayList<T>();
Gson gson = new Gson();


JsonArray array= json.getAsJsonArray();
Iterator<JsonElement> iterator = array.iterator();


while(iterator.hasNext()){
JsonElement json2 = (JsonElement)iterator.next();
T object = (T) gson.fromJson(json2, (Class<?>)type);
newArray.add(object);
}


return newArray;
}


}

JSONParsingTest.java:

public class JSONParsingTest {


List<World> worlds;


@Test
public void grantThatDeserializerWorksAndParseObjectArrays(){


String worldAsString = "{\"worlds\": [" +
"{\"name\":\"name1\",\"id\":1}," +
"{\"name\":\"name2\",\"id\":2}," +
"{\"name\":\"name3\",\"id\":3}" +
"]}";


GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Collection.class, new CollectionDeserializer());
Gson gson = builder.create();
Object decoded = gson.fromJson((String)worldAsString, JSONParsingTest.class);


assertNotNull(decoded);
assertTrue(JSONParsingTest.class.isInstance(decoded));


JSONParsingTest decodedObject = (JSONParsingTest)decoded;
assertEquals(3, decodedObject.worlds.size());
assertEquals((Long)2L, decodedObject.worlds.get(1).getId());
}
}

World.java:

public class World {
private String name;
private Long id;


public void setName(String name) {
this.name = name;
}


public String getName() {
return name;
}


public Long getId() {
return id;
}


public void setId(Long id) {
this.id = id;
}


}
Type listType = new TypeToken<List<Post>>() {}.getType();
List<Post> posts = new Gson().fromJson(jsonOutput.toString(), listType);

Some of the answers of this post are valid, but using TypeToken, the Gson library generates a Tree objects whit unreal types for your application.

To get it I had to read the array and convert one by one the objects inside the array. Of course this method is not the fastest and I don't recommend to use it if you have the array is too big, but it worked for me.

It is necessary to include the Json library in the project. If you are developing on Android, it is included:

/**
* Convert JSON string to a list of objects
* @param sJson String sJson to be converted
* @param tClass Class
* @return List<T> list of objects generated or null if there was an error
*/
public static <T> List<T> convertFromJsonArray(String sJson, Class<T> tClass){


try{
Gson gson = new Gson();
List<T> listObjects = new ArrayList<>();


//read each object of array with Json library
JSONArray jsonArray = new JSONArray(sJson);
for(int i=0; i<jsonArray.length(); i++){


//get the object
JSONObject jsonObject = jsonArray.getJSONObject(i);


//get string of object from Json library to convert it to real object with Gson library
listObjects.add(gson.fromJson(jsonObject.toString(), tClass));
}


//return list with all generated objects
return listObjects;


}catch(Exception e){
e.printStackTrace();
}


//error: return null
return null;
}

you can get List value without using Type object.

EvalClassName[] evalClassName;
ArrayList<EvalClassName> list;
evalClassName= new Gson().fromJson(JSONArrayValue.toString(),EvalClassName[].class);
list = new ArrayList<>(Arrays.asList(evalClassName));

I have tested it and it is working.

You can easily do this in Kotlin using the following code:

val fileData = "your_json_string"
val gson = GsonBuilder().create()
val packagesArray = gson.fromJson(fileData , Array<YourClass>::class.java).toList()

Basically, you only need to provide an Array of YourClass objects.

[
{
id : '1',
title: 'sample title',
....
},
{
id : '2',
title: 'sample title',
....
},
...
]

Check Easy code for this output

 Gson gson=new GsonBuilder().create();
List<Post> list= Arrays.asList(gson.fromJson(yourResponse.toString,Post[].class));

To conver in Object Array

Gson gson=new Gson();
ElementType [] refVar=gson.fromJson(jsonString,ElementType[].class);

To convert as post type

Gson gson=new Gson();
Post [] refVar=gson.fromJson(jsonString,Post[].class);

To read it as List of objects TypeToken can be used

List<Post> posts=(List<Post>)gson.fromJson(jsonString,
new TypeToken<List<Post>>(){}.getType());

in Kotlin :

val jsonArrayString = "['A','B','C']"


val gson = Gson()


val listType: Type = object : TypeToken<List<String?>?>() {}.getType()


val stringList : List<String> = gson.fromJson(
jsonArrayString,
listType)