96

This is my JSON Array :-

[ 
    {
        "firstName" : "abc",
        "lastName" : "xyz"
    }, 
    {
        "firstName" : "pqr",
        "lastName" : "str"
    } 
]

I have this in my String object. Now I want to convert it into Java object and store it in List of java object. e.g. In Student object. I am using below code to convert it into List of Java object : -

ObjectMapper mapper = new ObjectMapper();
StudentList studentList = mapper.readValue(jsonString, StudentList.class);

My List class is:-

public class StudentList {

    private List<Student> participantList = new ArrayList<Student>();

    //getters and setters
}

My Student object is: -

class Student {

    String firstName;
    String lastName;

    //getters and setters
}

Am I missing something here? I am getting below exception: -

Exception : com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.aa.Student out of START_ARRAY token
6
  • You are trying deserialize List into Student Commented Jun 16, 2017 at 12:36
  • Specifically: mapper.readValue(jsonString, Student.class) serializes a Student, not "a Student, or List of Students if the json looks like a List." You should use a TypeReference. Commented Jun 16, 2017 at 12:38
  • @yshavit: -I have updated the question. Sorry for that. Please look into it once again. Commented Jun 16, 2017 at 12:42
  • 1
    Your JSON doesn't look like {"participantList" : []}. That's what the error is trying to tell you Commented Jun 16, 2017 at 12:43
  • here is working solution extract data from JSON string array Commented Apr 20, 2020 at 11:06

11 Answers 11

186

You are asking Jackson to parse a StudentList. Tell it to parse a List (of students) instead. Since List is generic you will typically use a TypeReference

List<Student> participantJsonList = mapper.readValue(jsonString, new TypeReference<List<Student>>(){});
Sign up to request clarification or add additional context in comments.

3 Comments

perfect answer. Always works. But I have a follow-up question. What if Student POJO has a nested hashmap structure and jsonString has a piece which should be mapped to this nested hashmap. Can someone tell how can I achieve that?
Well, I understood what I was trying to achieve. I had to change the JSON structure (which I had the liberty to). [ { "id": "1", "name": "XYZ", "thisHasToBeHashMap" : { "key1" : "value1" , "key2" :"value2" } }] Having this structure is implicitly converted using TypeReference<List<Student>>
It can be simplified to List<Student> participantJsonList = mapper.readValue(jsonString, new TypeReference<>(){});
17

For any one who looks for answer yet:

1.Add jackson-databind library to your build tools like Gradle or Maven

2.in your Code:

ObjectMapper mapper = new ObjectMapper();

List<Student> studentList = new ArrayList<>();

studentList = Arrays.asList(mapper.readValue(jsonStringArray, Student[].class));

Comments

6

You can also use Gson for this scenario.

Gson gson = new Gson();
NameList nameList = gson.fromJson(data, NameList.class);

List<Name> list = nameList.getList();

Your NameList class could look like:

class NameList{
 List<Name> list;
 //getter and setter
}

1 Comment

This solution is more simple StackOverflow. It use TypeToken classe.
5

You can use below class to read list of objects. It contains static method to read a list with some specific object type. It is included Jdk8Module changes which provide new time class supports too. It is a clean and generic class.

List<Student> students = JsonMapper.readList(jsonString, Student.class);

Generic JsonMapper class:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.io.IOException;
import java.util.*;

import java.util.Collection;

public class JsonMapper {

    public static <T> List<T> readList(String str, Class<T> type) {
        return readList(str, ArrayList.class, type);
    }

    public static <T> List<T> readList(String str, Class<? extends Collection> type, Class<T> elementType) {
        final ObjectMapper mapper = newMapper();
        try {
            return mapper.readValue(str, mapper.getTypeFactory().constructCollectionType(type, elementType));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static ObjectMapper newMapper() {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.registerModule(new JavaTimeModule());
        mapper.registerModule(new Jdk8Module());
        return mapper;
    }
}

1 Comment

This is solution for generic methods like <T> List<T> asList(String json, Class<T> clazz). Without this objects will be as Map, but not as T.
4

use below simple code, no need to use any other library, besides GSON

String list = "your_json_string";
Gson gson = new Gson();                         
Type listType = new TypeToken<ArrayList<YourClassObject>>() {}.getType();
ArrayList<YourClassObject> users = new Gson().fromJson(list , listType);

1 Comment

"No need to use any library"... but you're very clearly using GSON (which already has an answer provided above)?!
2

I made a method to do this below called jsonArrayToObjectList. Its a handy static class that will take a filename and the file contains an array in JSON form.

 List<Items> items = jsonArrayToObjectList(
            "domain/ItemsArray.json",  Item.class);

    public static <T> List<T> jsonArrayToObjectList(String jsonFileName, Class<T> tClass) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        final File file = ResourceUtils.getFile("classpath:" + jsonFileName);
        CollectionType listType = mapper.getTypeFactory()
            .constructCollectionType(ArrayList.class, tClass);
        List<T> ts = mapper.readValue(file, listType);
        return ts;
    }

1 Comment

This is really a good option among others because this is a simple generic function for any POJO Class
1
StudentList studentList = mapper.readValue(jsonString,StudentList.class);

Change this to this one

StudentList studentList = mapper.readValue(jsonString, new TypeReference<List<Student>>(){});

Comments

0

I have resolved this one by creating the POJO class (Student.class) of the JSON and Main Class is used for read the values from the JSON in the problem.

   **Main Class**

    public static void main(String[] args) throws JsonParseException, 
       JsonMappingException, IOException {

    String jsonStr = "[ \r\n" + "    {\r\n" + "        \"firstName\" : \"abc\",\r\n"
            + "        \"lastName\" : \"xyz\"\r\n" + "    }, \r\n" + "    {\r\n"
            + "        \"firstName\" : \"pqr\",\r\n" + "        \"lastName\" : \"str\"\r\n" + "    } \r\n" + "]";

    ObjectMapper mapper = new ObjectMapper();

    List<Student> details = mapper.readValue(jsonStr, new 
      TypeReference<List<Student>>() {      });

    for (Student itr : details) {

        System.out.println("Value for getFirstName is: " + 
                  itr.getFirstName());
        System.out.println("Value for getLastName  is: " + 
                 itr.getLastName());
    }
}

**RESULT:**
         Value for getFirstName is: abc
         Value for getLastName  is: xyz
         Value for getFirstName is: pqr
         Value for getLastName  is: str


 **Student.class:**

public class Student {
private String lastName;

private String firstName;

public String getLastName() {
    return lastName;
}

public String getFirstName() {
    return firstName;
} }

2 Comments

While this code may answer the question, it would be better to include some context, explaining how it works and when to use it. Code-only answers are not useful in the long run.
@AlexRiabov have added the context to it.
0

Gson only Solution

the safest way is to iterate over json array by JsonParser.parseString(jsonString).getAsJsonArray() and parase it's elements one by one by checking jsonObject.has("key").

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.Data;
@Data
class Foo {
    String bar;
    Double tar;
}
JsonArray jsonArray = JsonParser.parseString(jsonString).getAsJsonArray();
List<Foo> objects = new ArrayList<>();
jsonArray.forEach(jsonElement -> {
    objectList.add(JsonToObject(jsonElement.getAsJsonObject()));
});
Foo parseJsonToFoo(JsonObject jsonObject) {
    Foo foo = new Foo();
    if (jsonObject.has("bar")) {
        String data = jsonObject.get("bar").getAsString();
        foo.setBar(data);
    }
    if (jsonObject.has("tar")) {
        Double data = jsonObject.get("tar").getAsDouble();
        foo.setTar(data);
    }
    return foo;
}

Comments

0
In your json , top most element name should be matched with the name of variable in your wrapper class. That will Jacson to convert my json into participantJsonList.
{
"participantJsonList" : [ 
    {
        "firstName" : "abc",
        "lastName" : "xyz"
    }, 
    {
        "firstName" : "pqr",
        "lastName" : "str"
    } 
]
}

Comments

-1

Try this. It works with me. Hope you too!

List<YOUR_OBJECT> testList = new ArrayList<>();
testList.add(test1);

Gson gson = new Gson();

String json = gson.toJson(testList);

Type type = new TypeToken<ArrayList<YOUR_OBJECT>>(){}.getType();

ArrayList<YOUR_OBJECT> array = gson.fromJson(json, type);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.