84

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
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
Nitesh
  • 1,477
  • 5
  • 23
  • 34
  • You are trying deserialize `List` into `Student` – ByeBye Jun 16 '17 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](https://fasterxml.github.io/jackson-core/javadoc/2.0.0/com/fasterxml/jackson/core/type/TypeReference.html). – yshavit Jun 16 '17 at 12:38
  • @yshavit: -I have updated the question. Sorry for that. Please look into it once again. – Nitesh Jun 16 '17 at 12:42
  • 1
    Your JSON doesn't look like `{"participantList" : []}`. That's what the error is trying to tell you – OneCricketeer Jun 16 '17 at 12:43
  • **here is working solution** [extract data from JSON string array](https://stackoverflow.com/a/61320877/8968815) – Mehul Boghra Apr 20 '20 at 11:06
  • **Here is working solution.** [Extract data form JSON string array and convert into List](https://stackoverflow.com/a/61320877/8968815) – Mehul Boghra Apr 20 '20 at 11:09

10 Answers10

163

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>>(){});
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
  • 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? – old_soul_on_the_run Dec 09 '19 at 20:28
  • 1
    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> – old_soul_on_the_run Dec 09 '19 at 21:09
  • It can be simplified to `List participantJsonList = mapper.readValue(jsonString, new TypeReference<>(){});` – Kxrr Apr 02 '22 at 06:34
13

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));
Sobhan
  • 1,280
  • 1
  • 18
  • 31
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
}
Pankaj Jaiswal
  • 689
  • 8
  • 16
  • This solution is more simple [StackOverflow](https://stackoverflow.com/a/14673950/6635967). It use `TypeToken` classe. – HRoux Oct 02 '18 at 17:23
4

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;
    }
}
erhun
  • 3,549
  • 2
  • 35
  • 44
3

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);
Alexandros Kourtis
  • 539
  • 2
  • 6
  • 20
Prakash Reddy
  • 944
  • 10
  • 20
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;
    }
javaPlease42
  • 4,699
  • 7
  • 36
  • 65
1
StudentList studentList = mapper.readValue(jsonString,StudentList.class);

Change this to this one

StudentList studentList = mapper.readValue(jsonString, new TypeReference<List<Student>>(){});
monstereo
  • 830
  • 11
  • 31
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;
} }
Atul KS
  • 908
  • 11
  • 21
  • 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. – Alex Riabov Dec 28 '18 at 06:41
  • @AlexRiabov have added the context to it. – Atul KS Dec 29 '18 at 06:37
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;
}
pradeexsu
  • 1,029
  • 1
  • 10
  • 27
-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);