Cách phân tích cú pháp Mảng JSON với Gson


84

Tôi muốn phân tích cú pháp các mảng JSON và sử dụng gson. Đầu tiên, tôi có thể ghi đầu ra JSON, máy chủ đang phản hồi với máy khách một cách rõ ràng.

Đây là đầu ra JSON của tôi:

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

Tôi đã thử cấu trúc này để phân tích cú pháp. Một lớp, phụ thuộc vào một arrayArrayListcho tất cả 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; 
      } 
 }

Đăng lớp:

 public class Post {

      private String id;
      private String title;

      /* getters & setters */
 }

Khi tôi cố gắng sử dụng gson không có lỗi, không có cảnh báo và không có nhật ký:

 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());

Có gì sai, tôi có thể giải quyết như thế nào?

Câu trả lời:


247

Bạn có thể phân tích cú pháp JSONArraytrực tiếp, không cần kết thúc Postlớp của mình PostEntitymột lần nữa và cũng không cần mới JSONObject().toString():

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

Hy vọng rằng sẽ giúp.


Tôi đã xóa lớp PostEntity và thay vào đó đã thử đoạn mã của bạn. Vẫn không thay đổi. Cảm ơn.
Ogulcan Orhan

Cuối cùng đã hoạt động chính xác và hiệu quả. Cảm ơn bạn rất nhiều lần nữa.
Ogulcan Orhan

Xin chào cách phân tích cú pháp dữ liệu mảng json lồng nhau như thế này .... [{"firstName": "Bidhan", "lastName": "Chatterjee"}, [{"type": "personal", "number": "09832209761" }, {"type": "fax", "number": "91-342-2567692"}]]
KK_07k11A0585

Có lợi ích khi sử dụng TypeToken không? Từ các thử nghiệm của tôi, gson dường như xử lý trường Danh sách <Đối tượng> mà không sử dụng TypeToken.
greg7gkb

Đây là thực sự hữu ích cho tôi
Bhavesh Kaila

6

Tôi đang tìm cách phân tích cú pháp các mảng đối tượng theo một cách chung chung hơn; đây là đóng góp của tôi:

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

}

@ Có tôi không hiểu làm thế nào điều này chuyển đổi từ JsonArray thành Danh sách <Thế giới>
ARK

Về cơ bản, nó sử dụng CollectionDeserializer cho mọi Bộ sưu tập được tìm thấy trong quá trình giải mã GSON. Về phía CollectionDeserializer, suy luận thông qua tham số chung của Collection mà lớp đại diện cho lưu trữ đối tượng trên bộ sưu tập mà nó nên giải mã hóa. Tôi hy vọng điều này đã trả lời câu hỏi của bạn. Nếu bạn vẫn còn nghi ngờ, vui lòng liên hệ với tôi tại [miere00 at gmail.com].
Miere

Xin chào @Miere, giải pháp này không xử lý được câu hỏi ban đầu. JSONParsingTest của bạn là một đối tượng có một mảng bên trong. Làm cách nào để bạn sử dụng CollectionDeserializer của mình để chỉ phân tích cú pháp một mảng chứ không phải một mảng được bao bọc trong một đối tượng?
zkon

5

Để chuyển đổi trong mảng đối tượng

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

Để chuyển đổi dưới dạng bài đăng

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

Để đọc nó dưới dạng Danh sách các đối tượng, TypeToken có thể được sử dụng

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

còn với ArrayList <Post> thì sao?
gumuruh

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

6
Mặc dù điều này có thể trả lời câu hỏi, nhưng nó không cung cấp bất kỳ ngữ cảnh nào để giải thích cách thức hoặc lý do. Cân nhắc thêm một hoặc hai câu để giải thích câu trả lời của bạn.
brandonscript

3

Một số câu trả lời của bài đăng này là hợp lệ, nhưng bằng cách sử dụng TypeToken, thư viện Gson tạo ra một đối tượng Tree với các kiểu không có thực cho ứng dụng của bạn.

Để có được nó, tôi phải đọc mảng và chuyển đổi từng đối tượng bên trong mảng. Tất nhiên phương pháp này không phải là nhanh nhất và tôi không khuyên bạn nên sử dụng nó nếu bạn có mảng quá lớn, nhưng nó đã hiệu quả với tôi.

Cần phải đưa thư viện Json vào dự án. Nếu bạn đang phát triển trên Android, nó được bao gồm:

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

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

Kiểm tra mã Easy cho đầu ra này

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

1

Bạn có thể dễ dàng thực hiện việc này trong Kotlin bằng đoạn mã sau:

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

Về cơ bản, bạn chỉ cần cung cấp một Arraytrong YourClasscác đối tượng.


Tại sao bạn sử dụng PrettyPrinting?
Antroid

@antroid Tôi quên để xoá bỏ nó ^^
xarlymg89

0

bạn có thể nhận giá trị Danh sách mà không cần sử dụng đối tượng Loại .

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

Tôi đã thử nghiệm nó và nó đang hoạt động.


0

trong 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.