Jak deserialize json w Map<String, Property>, gdzie Property to Abstract class?

0

Cześć wszystkim, jak można deserialize json w Map<String, Property> z Controllera, gdzie Property to Abstract class? Przez cały dzień łapię w mordę ten długi exception

Property

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "propertyType")
@JsonSubTypes({
        @JsonSubTypes.Type(value = BooleanProperty.class, name = "boolean"),
        @JsonSubTypes.Type(value = DateProperty.class, name = "date"),
        @JsonSubTypes.Type(value = TextProperty.class, name = "text"),
        @JsonSubTypes.Type(value = NumericalProperty.class, name = "numeric"),
        @JsonSubTypes.Type(value = SelectionProperty.class, name = "selection"),
})
@EqualsAndHashCode
@ToString
@Data
public abstract class Property {

    @NonNull
    public String name = "name";
    public String description = "Standard description";
    public PropertyFlags flags;


    public Property() {
    }

    public Property(@NonNull String name,
                    String description,
                    PropertyFlags flags) {
        this.name = name;
        this.flags = flags;
        this.description = description;
    }

DTO

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AssetPrototypeDTO {

        private String id;
        private String name;
        private String desc;
        private Map<String, Property> assetProperties;
        private List<Tag> tags;
        private String icon;

Exception

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.util.LinkedHashMap<java.lang.String,com.immotef.inspector.commons.property.Property>` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: 
Cannot deserialize instance of `java.util.LinkedHashMap<java.lang.String,com.immotef.inspector.commons.property.Property>` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 6, column: 7] (through reference chain: com.immotef.inspector.assets.prototypes.AssetPrototypeDTO["assetProperties"])]
0
  1. Wyjmij to ze środowiska Spinga (nie myśl Springiem) i na samym Jacksonie zrób testy
  2. generalnie deserializacja z JSON do klas abstrakcyjnych / innego dziedziczenia jest teoretycznie niemożliwa / trudna, bo w JSON nie ma informacji o typie, tylko o wartościach *) Ten sam problem mają w C#, wynika z istoty JSON.
  3. w powiązaniu z 1. Jackson jest na tyle dobrą biblioteką, że ma środki do wymuszania typu
    Tu od p.4 coś jest
    https://www.baeldung.com/jackson-object-mapper-tutorial

Podkreślę: nie rozwiązywałem takiego problemu, ale kilkakrotnie z dobrej strony poznałem Jacksona

*) dlatego czasem żal starego dobrego XML, **mógł **mieć informację o typie. Ach ten "postęp"

1

@Władyslaw Parchomenko: a możesz nam pokazać jak wygląda JSON który próbujesz zdeserializować? Błąd jasno sugeruje że masz tam jakąś listę i z listy nie da się zrobić mapy. Może masz tam jednoelementową listę w tym jsonie tzn np. [{"x":"y"}] zamiast {"x":"y"}?

0

{
"id":"61221308dc09fa35c3f6ffa7",
"name":"Floor",
"desc":"Floor Asset Prototypejajajajjajaj",
"assetProperties":[
{
"property":{
"propertyType" : "numeric",
"name" : "Floor Number",
"description" : "some description",
"flags" : {
"isConfigurable" : true,
"isUpdatable" : true,
"isMandatory" : true
},
"value": 3,
"hasRange": false,
"decimalPoints": 0
},
"procedureIds":[]
}
],
"tags":["floor"],
"icon":""
}

0

No to chyba widzisz ze to się nijak ma jedno z drugim o_O

"assetProperties":[

To jest lista (!)

private Map<String, Property> assetProperties;

To jest mapa. Jak dostaniesz listę [{"x":"y"},{"x":"z"}] to w jaki sposób ma się z tego niby zrobić mapa?

0
{
   "id":"61221308dc09fa35c3f6ffa7",
   "name":"Floor",
   "desc":"Floor Asset Prototypejajajajjajaj",
   "assetProperties":
      {
         "property" : {
            "propertyType" : "numeric",
            "name" : "Floor Number",
            "description" : "some description",
            "flags" : {
               "isConfigurable" : true,
               "isUpdatable" : true,
               "isMandatory" : true
            },
            "value": 3,
            "hasRange": false,
            "decimalPoints": 0
         },
         "procedureIds":[]
      },
   "tags":["floor"],
   "icon":""
}
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected token (END_ARRAY), expected VALUE_STRING: need JSON String that contains type id (for subtype of com.immotef.inspector.commons.property.Property); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (END_ARRAY), expected VALUE_STRING: need JSON String that contains type id (for subtype of com.immotef.inspector.commons.property.Property)
 at [Source: (PushbackInputStream); line: 20, column: 26] (through reference chain: com.immotef.inspector.assets.prototypes.AssetPrototypeDTO["assetProperties"]->java.util.LinkedHashMap["procedureIds"])]
2

No ok i teraz masz już normalny błąd wynikający z tego że chcesz deserializować pod-klasę i jackson musi skądś wiedzieć którą klasę wybrać. Widocznie coś jest źle z tymi jacksonowymi adnotacjami. Moja rada: zrób sobie kilka obiektów i zserializuj do jsona i zobacz co jackson wyprodukował i jak to powinno wyglądać a potem porównaj z tym co masz.

0

Pole procedureIds u Ciebie jest pustą listą, a zdefiniowałeś, że powinien to być obiekt Property. Zmień to pole to poprawny obiekt lub usuń z jsona

1 użytkowników online, w tym zalogowanych: 0, gości: 1