简体   繁体   中英

Java Jackson deserialize an object containing a list of object with/without custom Deserializer?

I've got a JSON input like this

{
"slices": [{
        "slice": {
            "boundedBy": {
                "Envelope": {
                    "axisLabels": "Lat Long ansi",
                    "lowerCorner": "-44.975 111.975 \"2003-01-01T00:00:00+00:00\"",
                    "upperCorner": "-8.975 155.975 \"2003-01-01T00:00:00+00:00\"",
                    "srsDimension": 3
                }
            },
            "fileReferenceHistory": "/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20030101-20030110-H01V06-1.0_MERIS-FR-LAI-HA.tiff",
            "local_metadata_key": "value_1"
        }
    },
    {
        "slice": {
            "boundedBy": {
                "Envelope": {
                    "axisLabels": "Lat Long ansi",
                    "lowerCorner": "-44.975 111.975 \"2003-10-01T00:00:00+00:00\"",
                    "upperCorner": "-8.975 155.975 \"2003-10-01T00:00:00+00:00\"",
                    "srsDimension": 3
                }
            },
            "fileReferenceHistory": "/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20031001-20031010-H00V10-1.0_MERIS-FR-LAI-HA.tiff",
            "local_metadata_key": "value_2"
        }
    }
],
"Title": "Drought code", 
// other keys:values
}

with "slices" is an array of "slice" objects. Out of "slices" is any "keys":"values" but it is not the problem.

Then, I have a POJO class

public class CoverageMetadata {

       @JsonProperty(value = "slices")
       @JacksonXmlElementWrapper(useWrapping = false)
       private List<LocalMetadata> localMetadataList;

       private Map<String, String> globalMetadataAttributesMap;

       @JsonAnySetter
       public void addKeyValue(String key, String value) {
            this.globalMetadataAttributesMap.put(key, value);
       }

       @JsonAnyGetter
       public Map<String, String> getGlobalAttributesMap() {
            return globalMetadataAttributesMap;
       }

       // other gettters, setters without Jackson annotations

}

and a class inside the list:

public class LocalMetadata {

    public static final String LOCAL_METADATA_TAG = "slice";

    private Map<String, String> localMetadataAttributesMap;

    private BoundedBy boundedBy;

    @JsonAnySetter
    // NOTE: To map an unknown list of properties, must use this annotation
    public void addKeyValue(String key, String value) {
        this.localMetadataAttributesMap.put(key, value);
    }


    public LocalMetadata() {
        this.localMetadataAttributesMap = new LinkedHashMap<>();
        this.boundedBy = new BoundedBy();
    }

    @JsonAnyGetter
    // NOTE: to unwrap the "map" from { "map": { "key": "value" } }, only keep { "key": "value" }
    public Map<String, String> getLocalMetadataAttributesMap() {
        return localMetadataAttributesMap;
    }

    public BoundedBy getBoundedBy() {
        return this.boundedBy;
    }

    public void setBoundedBy(BoundedBy boundedBy) {
        this.boundedBy = boundedBy;
    }

    public LocalMetadata(Map<String, String> localMetadataAttributesMap, BoundedBy boundedBy) {
        this.localMetadataAttributesMap = localMetadataAttributesMap;
        this.boundedBy = boundedBy;
    }
}

And the basic code to deserialize JSON to object

ObjectMapper objectMapper = new ObjectMapper();
CoveageMetadata coverageMetadata = objectMapper.readValue(metadata, CoverageMetadata.class);

When I try to deserialize the JSON input to CoverageMetadata object, I got the error

    Cannot deserialize coverage's metadata in XML/JSON by Jackson, error: Can not deserialize instance of java.lang.String out of START_OBJECT token
 at [Source: {"slices":[{"slice":{"boundedBy":{"Envelope":{"axisLabels":"Lat Long ansi","srsDimension":3,"lowerCorner":"-44.975 111.975 \"2003-01-01T00:00:00+00:00\"","upperCorner":"-8.975 155.975 \"2003-01-01T00:00:00+00:00\""}},"local_metadata_key":"value_1","fileReferenceHistory":"/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20030101-20030110-H01V06-1.0_MERIS-FR-LAI-HA.tiff"}}],"Title":"Drought code"}; line: 1, column: 21] (through reference chain: petascope.core.gml.metadata.model.CoverageMetadata["slices"]->java.util.ArrayList[0]->petascope.core.gml.metadata.model.LocalMetadata["slice"]).

How can I deserialize this JSON input String to CoverageMetadataObject with each "slice" element will be mapped to a LocalMetadata object?

The simple answer is I create another POJO class to hold the "slices" list, in CoverageMetadata class, it will have

public class CoverageMetadata {

     private Map<String, String> globalMetadataAttributesMap; 
     @JsonProperty(value = "slices")    
     private LocalMetadata localMetadata;

...
}

New POJO class (class LocalMetadata before was renamed to LocalMetadataChild)

public class LocalMetadata {

    @JsonProperty(value = "slice")
    // This is the most important thing to avoid duplicate <slices><slices> when serializing in XML.
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<LocalMetadataChild> localMetadataList;

    public LocalMetadata(List<LocalMetadataChild> localMetadataList) {
        this.localMetadataList = localMetadataList;
    }

    public LocalMetadata() {
        this.localMetadataList = new ArrayList<>();
    }

    public List<LocalMetadataChild> getLocalMetadataList() {
        return localMetadataList;
    }

    public void setLocalMetadataList(List<LocalMetadataChild> localMetadataList) {
        this.localMetadataList = localMetadataList;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM