How to parse JSON array response using Jackson?

2019-04-17 10:11发布

I'm building a RESTful client for Android and I have a question about Jackson.
I get the following JSON response:

{
    "cars": [
        {
            "active": "true",
            "carName": "××× ×'פ ס×××ק×",
            "categoryId": {
                "licenseType": "××××××",
                "licenseTypeId": "1"
            },
            "id": "1401268",
            "insuranceDate": "2011-07-05T00:00:00+03:00",
            "lessonLength": "45",
            "licenseDate": "2011-07-05T00:00:00+03:00",
            "price": "100",
            "productionYear": "2009-07-05T00:00:00+03:00"
        },
        {
            "active": "true",
            "carName": "××©× ×××",
            "categoryId": {
                "licenseType": "×ש××ת",
                "licenseTypeId": "4"
            },
            "id": "1589151",
            "insuranceDate": "2011-04-13T00:00:00+03:00",
            "lessonLength": "30",
            "licenseDate": "2011-04-13T00:00:00+03:00",
            "price": "120",
            "productionYear": "2004-04-12T00:00:00+03:00"
        },............. etc

each is a car from a class that looks like this:

public class Cars implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer id;
    private String carName;
    private Date productionYear;
    private Date insuranceDate;
    private Date licenseDate;
    private Boolean active;
    private Long price;
    private Integer lessonLength;
    private Date dayStart;
//    private Collection<Students> studentsCollection;
//    private Collection<Lessons> lessonsCollection;
    private LicenseTypes categoryId;
//    private Collection<Kilometers> kilometersCollection;

    public Cars() {
    }

    public Cars(Integer id) {
        this.id = id;
    }

    public Cars(Integer id, String carName) {
        this.id = id;
        this.carName = carName;
    }

    public Integer getId() {
        return id;
    }

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

I've been trying to parse it automatically with Jackson with little/no success.. Is it even possible to parse and convert it to an object automatically? I can't find this anywhere online..
If you have some sort of example for this specific type of server response please point me there, or if someone can generally explain how to do it with Jackson or with some other tool, I would greatly appreciate it.


EDIT: Thanks all. I managed to make Jackson work by removing the {"cars": from the beginning of the result string, and the } from the end of the result string. After doing that, Jackson understood it was an array and did everything by itself. So for anyone else who got problems with those sort of things: A JSON array should start with [ and end with ] and each element inside should start with { and end with }. No annotations needed, Jackson can find the members by itself.

4条回答
虎瘦雄心在
2楼-- · 2019-04-17 10:38

Jackson certainly can handle this. You need couple more pieces however. First, the request object to bind to:

public class Response {
  public List<Cars> cars;
}

and you also need to either add setters to Cars, make fields public (Jackson only considers public fields for auto-detection), or add following annotation to Cars class:

@JsonAutoDetect(fieldVisibility=Visibility.ANY)

(so that private fields are considered properties as well).

And with that, you do:

Response response = new ObjectMapper().readValue(jsonInput, Response.class);
查看更多
叼着烟拽天下
3楼-- · 2019-04-17 10:48

I did something similar using the Gson library (http://code.google.com/p/google-gson/). I found it easier to use than Jackson.

Here's an example of parsing a response for a contact that looks like it would translate well to your Cars example:

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
...

public class TestContact implements Serializable {

    private static final long serialVersionUID = 1L;

    @SerializedName("Name")        private String mName;
    @SerializedName("PhoneNumber") private String mPhoneNumber;
    @SerializedName("Address1")    private String mAddress1;
    @SerializedName("Address2")    private String mAddress2;
    @SerializedName("City")        private String mCity;
    @SerializedName("State")       private String mState;
    @SerializedName("Zip")         private String mZip;
    @SerializedName("Website")     private String mWebsite;
    @SerializedName("Email")       private String mEmail;

    public static TestContact create(JSONObject response) throws JSONException {
        Gson gson = new Gson();
        TestContact contact = gson.fromJson(response.toString(), TestContact.class);  

        return contact;
    }

    public static ArrayList<TestContact> createList(JSONObject response) throws JSONException {
        ArrayList<TestContact> contacts = new ArrayList<TestContact>();
        JSONArray contactResponses = response.getJSONArray("Contacts");

        for (int i = 0; i < contactResponses.length(); i++) {
            JSONObject contactResponse = contactResponses.getJSONObject(i);
            contacts.add(create(contactResponse));
        }

        return contacts;
    }

    ...
}
查看更多
仙女界的扛把子
4楼-- · 2019-04-17 10:54

I don't have any knowledge of Jackson I'm afraid, but a possibility could be to have a constructor in the Cars class that takes as a parameter an element of a JSON array (whatever type that is in Jackson). The constructor would then pull out the values from each key of the JSON car entry and populate the class members as appropriate.

查看更多
唯我独甜
5楼-- · 2019-04-17 10:55

Here's a simple test I used at some point to understand how Jackson serializes/deserializes JSON arrays and objects:

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class JacksonTest {

  private final ObjectMapper mapper = new ObjectMapper();

  public static class Book {
    public String title;
    public String author;
  }

  @Test
  public void readWriteJsonObject() throws JsonGenerationException, JsonMappingException, IOException {
    String json = mapper.writeValueAsString(new Book() {{
      title  = "Real World Haskell";
      author = "Don Stewart";
    }});

    Book book = mapper.readValue(json, Book.class);

    assertEquals("Real World Haskell", book.title);
    assertEquals("Don Stewart", book.author);
  }

  @Test
  @SuppressWarnings("serial")
  public void readWriteJsonArray() throws JsonGenerationException, JsonMappingException, IOException {
    List<Book> books = new ArrayList<Book>() {{
      add(new Book() {{
        title  = "Real World Haskell";
        author = "Don Stewart";
      }});
      add(new Book() {{
        title  = "Learn You Some Erlang";
        author = "Fred T. Herbert";
      }});
    }};

    String json = mapper.writeValueAsString(books);
    books = mapper.readValue(json, new TypeReference<List<Book>>() {});

    assertEquals("Real World Haskell", books.get(0).title);
    assertEquals("Don Stewart", books.get(0).author);

    assertEquals("Learn You Some Erlang", books.get(1).title);
    assertEquals("Fred T. Herbert", books.get(1).author);
  }
}
查看更多
登录 后发表回答