4

I'm trying to deserialize a JSON Array with JSONB.

JSON

[
  {
    "id": "1",
    "animal": "dog",
    "age": "3"
  },
  {
    "id": "2",
    "animal": "cat",
    "age": "5"
  }
]

Controller

Jsonb jsonb = JsonbBuilder.create();    
Animal animal;
AnimalsList animalsList;

public AnimalsList getAnimals() {
    try {
        animalsList = jsonb.fromJson("[{\"id\":\"1\",\"animal\":\"dog\",\"age\":\"3\"},{\"id\":\"2\",\"animal\":\"cat\",\"age\":\"5\"}]", AnimalsList.class);
    } catch (JSONException ex) {
        Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
    }
    return animalsList;
}

AnimalsList

public class AnimalsList implements Serializable{

    private List<Animal> list;

    public AnimalsList() {
    }

    public AnimalsList(List<Animal> list) {
        this.list = list;
    }

    // getter & setter
}

Animal

public class Animal implements Serializable{

    private int id;
    private String animal;
    private int age;

    public Animal() {
    }

    public Animal(int id, String animal, int age) {
        this.id = id;
        this.animal = animal;
        this.age = age;
    }

    // getter & setter
}

But I get the following error:

javax.json.bind.JsonbException: Can't deserialize JSON array into: class com.model.AnimalsList
Evgenij Reznik
  • 17,916
  • 39
  • 104
  • 181
  • 1
    Your json has an array type, you can't deserialize it to a single object (a `AnimalsList` object). You may try to deserialize your json directly into a `List` . – Arnaud Aug 12 '19 at 14:05
  • @Arnaud: Like this `List animals = jsonb.fromJson("[{...}]", List.class)`? – Evgenij Reznik Aug 12 '19 at 14:15
  • 4
    Maybe with `new ArrayList(){}.getClass().getGenericSuperclass()` instead of `List.class` , see here : https://javaee.github.io/jsonb-spec/users-guide.html . – Arnaud Aug 12 '19 at 14:18

2 Answers2

7

As written in the comment of Arnaud, this guide shows a solution:

List<Dog> dogs = new ArrayList<>();
dogs.add(falco);
dogs.add(cassidy);

// Create Jsonb and serialize
Jsonb jsonb = JsonbBuilder.create();
String result = jsonb.toJson(dogs);

// Deserialize back
dogs = jsonb.fromJson(result, new ArrayList<Dog>(){}.getClass().getGenericSuperclass());
Stefan Großmann
  • 866
  • 9
  • 20
  • 1
    The code works, but not when wrapped by the generic method. The generic method throws: `WARNING: Generic bound not found for type T declared in public static java.util.List fromJsonArray(jakarta.json.bind.Jsonb,java.lang.String).` – ARX Feb 25 '21 at 15:59
  • Followed by: `java.lang.ClassCastException: class java.util.HashMap cannot be cast to class my.package.MyType (java.util.HashMap is in module java.base of loader 'bootstrap'; my.package.MyType is in unnamed module of loader 'app')` – ARX Feb 25 '21 at 16:00
  • @ARX: The section with the generic method is removed from the post – Stefan Großmann Mar 03 '21 at 19:15
-2

If you're not restricted to just use JSON-B you can do it with ObjectMapper by TypeReferencing.

private ObjectMapper objectMapper = new ObjectMapper();
List<Animal> animals = objectMapper.readValue(json , new TypeReference<List<Animal>>(){});
Sanket Patel
  • 227
  • 1
  • 14