0

I have following Json and want to map this json as java pojo using spring webclient mono response. in this json keys data-1 and en are not constants and keep changing. for example it could be data-2 and fr or data-3 and it.

{
    "data": {
        "attributes": {
            "data-1": {
                "en": [
                    {
                        "id": 1,
                        "code": "GI",
                        "order": 10
                        
                    },
                    {
                        "id": 2,
                        "code": "TH",
                        "order": 10
                    }
                ]
            }
        }
    }
}

DTO structure :

@JsonInclude(JsonInclude.Include.NON_NULL)
public class ListData {
    private Map<String, Attributes> data;
}

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Attributes {
    private Map<String, Map<String, MyList>> attributes;
}

@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyList {
    private List<Entry> entryList;
}

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Entry {
    private String id;
    private String code;
    private String order;
    
}

here is webclient that deserialize json.

return WebClient.create("test.com")
                .get()
                .uri(getTestUri())
                .header(HttpHeaders.ACCEPT, Constants.ACCEPT_TYPE)
                .retrieve()
                .bodyToMono(ListData.class)
                .block();

Following is the error :

org.springframework.core.codec.CodecException: Type definition error: [simple type, class com.test.ListAttributes]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.test.ListAttributes` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

could someone help me on this, how can it be fixed.

knittl
  • 246,190
  • 53
  • 318
  • 364
keepmoving
  • 1,813
  • 8
  • 34
  • 74
  • Why is it trying to construct `ListAttributes`? I don't see this class in your code – knittl Apr 29 '21 at 19:12
  • I renamed all the classes but not in error. Its actually Attribtues – keepmoving Apr 30 '21 at 03:52
  • And the classes as you show them are the real classes? No getters/setters, i.e. only private fields which cannot be accessed? The error message clearly states "no Creators, like **default constructor**" and I don't see any custom constructor in the code of the question. Do you actually have defined constructors – therefore disabling the parameterless default constructor – and left them out from the question? – knittl Apr 30 '21 at 05:53
  • And looking once more at it, I think your DTOs are too deeply nested. The `Attributes` values don't map to an object containing a list, but map to a list directly – knittl Apr 30 '21 at 06:27

1 Answers1

1
{
    "data": {
        "attributes": {
            "data-1": {
                "en": [
                    {
                        "id": 1,
                        "code": "GI",
                        "order": 10
                        
                    },
                    {
                        "id": 2,
                        "code": "TH",
                        "order": 10
                    }
                ]
            }
        }
    }
}

"data-1" and "en" being variable keys imply that a doubly-nested Map is needed. The inner map maps strings to a List of objects (Entry objects in your specific case).

Therefore, the structure/type of the above JSON maps to the Java type:

class Container {
  public Data data;
  public Container() {}
}

class Data {
  public Map<String, Map<String, List<Entry>>> attributes;
  public Data() {}
}

class Entry {
  public long id;
  public String code;
  public long order;
  public Enrty() {}
}

Make sure your types are default-constructible and its fields can be set by Jackson

knittl
  • 246,190
  • 53
  • 318
  • 364