简体   繁体   中英

Error while deserializing Map<IgnoredCaseKey, Object> response from spring restTemplate

while calling API request from a service I get the following error:

org.springframework.http.converter.HttpMessageNotReadableException: 
JSON parse error: Cannot deserialize instance of `java.lang.String` out of 
START_OBJECT token; nested exception is 
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize 
instance of `java.lang.String` out of START_OBJECT token
 at [Source: (ByteArrayInputStream); line: 19, column: 30] (through reference chain: java.lang.Object[][0]->com.cellwize.network.mo.load.model.ManagedObject["a"]->java.util.LinkedHashMap["siPeriodicity"])

the json I'm trying to get is :

[ {
  "guid" : "e_guid_lncell:311|480|6535681",
  "uid" : "c3528280-0d50-3ad8-a5be-d2dbdfcb77fd",
  "parentUid" : "0306573b-e431-37ad-ae59-5435947548cf",
  "parentMoClass" : null,
  "originalId" : "025530_1",
  "metaType" : "sector",
  "vendor" : "e",
  "technology" : "4g",
  "references" : null,
  "updateCommandType" : null,
  "scopeId" : "f5ed648f-4b42-4033-9243-db2150840995",
  "snapshotId" : 2054717834413232,
  "base_key" : "025530_1;MC",
  "class" : "vsDataEUtranCellFDD",
  "a" : {
    "prsConfigIndexMapped" : "1",
    "siPeriodicity" : {
      "siPeriodicitySI1" : "16",
      "siPeriodicitySI10" : "64",
      "siPeriodicitySI2" : "64",
      "siPeriodicitySI3" : "64",
      "siPeriodicitySI4" : "64",
      "siPeriodicitySI5" : "64",
      "siPeriodicitySI6" : "64",
      "siPeriodicitySI7" : "64",
      "siPeriodicitySI8" : "64",
      "siPeriodicitySI9" : "64"
    }
  }
} ]

the function which requests the API call is :

    public Map<String, ManagedObject> mapMosToUids(Collection<String> uids) throws IOException {
        if (uids == null || uids.isEmpty()) {
            return Collections.emptyMap();
        }

        final String url = naasUrl + "/getMos/" + String.join(",", uids);
        ResponseEntity<ManagedObject[]> response = restTemplate.getForEntity(url, ManagedObject[].class);


        ManagedObject[] mos = response.getBody();
        return Arrays.stream(mos).collect(Collectors.toMap(mo -> mo.getUid().toString(), mo -> mo));
    }


the Pojo of the class is:


@JsonIgnoreProperties({"_id"})
public class ManagedObject{
    public static final String ATTRIBUTES_PREFIX = "a";
    public static final String GEN_ATTRIBUTES_PREFIX = "gen";
    public static final String PHY_ATTRIBUTES_PREFIX = "phy";
    public static final String BIT_ATTRIBUTES_PREFIX = "bit";

    public static final String META_PREFIX = "meta";
    public static final String CLASS_COLUMN = "class";
    public static final String BASEKEY_COLUMN = "base_key";
    public static final String NET_CTRL_KEY = "net_ctrl_uid";
    public static final String NETWORK_CONTROLLER = "netCtrl";
    public static final String META_TYPE_COLUMN = "meta_type";
    public static final String GUID_COLUMN = "guid";
    public static final String UID_COLUMN = "uid";
    public static final String PARENT_UID_COLUMN = "parent_uid";

    private static final StringDeduplicator STRING_DEDUPLICATOR = new StringDeduplicator();

    private String guid;
    private UUID uid;
    private UUID parentUid;
    private String parentMoClass;
    private String originalId;
    @JsonProperty(BASEKEY_COLUMN)
    private String originalName;
    @JsonProperty(CLASS_COLUMN)
    private String moClass;
    private String metaType;
    private String vendor;
    private String technology;
    @JsonProperty(ATTRIBUTES_PREFIX)
    private Map<IgnoredCaseKey, Object> attributes;
    private Map<String, String> references;
    @JsonProperty(META_PREFIX)
    private Map<String, String> meta;
    @JsonProperty(GEN_ATTRIBUTES_PREFIX)
    private Map<String, String> genAttributes;
    private String updateCommandType;

    @JsonProperty(PHY_ATTRIBUTES_PREFIX)
    private Map<String,String> phyAttributes;
    private UUID scopeId;
    private Long snapshotId;

    public ManagedObject() {
        this.attributes = new HashMap<>();
        this.meta = new HashMap<>();
        this.genAttributes = new HashMap<>();
        this.phyAttributes = new HashMap<>();
    }

    public ManagedObject(UUID uid, UUID parentUid, String moClass, Map<String, String> attributes) {
        this();

        this.uid = uid;
        this.parentUid = parentUid;
        this.moClass = moClass;

        copyAttributes(attributes, this.attributes);
    }
}```

I tried writing my own JsonDeserialize and it didn't work. If I get an object in the getForEntity and deserialize it with ObjectMapper by myself, a process which runs in steps it will eventually work but I'm looking for a better solution

Cannot deserialize instance of java.lang.String out of START_OBJECT token;

This exception means that you screwed up Jackson mapping.

My personal advice to you to simplify debugging, is when dealing with complex JSON structures, instead of mapping the whole structure at once, try doing so step by step. Going from the first level, deeper and deeper down slowly unveiling JsonNodes.

The error most likely is here, because IgnoredCaseKey is not a string, but a custom object. Try to declare attributes or a key-value pair as JsonNode, and walk downwards to find what's causing the error.

So your first step would be to replace this:

@JsonProperty(ATTRIBUTES_PREFIX)
private Map<IgnoredCaseKey, Object> attributes;

with this:

@JsonProperty(ATTRIBUTES_PREFIX)
private JsonNode attributes;

If that is not causing any errors, then the problem is this Map<IgnoredCaseKey, Object> is the wrong type for the given JSON object. If it does cause errors, the problem is elsewhere.

Since the structure of the JSON you provided is not accurate, I can't provide you with a specific answer, but hope this direction will help you troubleshoot more effectively.

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