Ошибка при десериализации ответа Map <IgnoredCaseKey, Object> от Spring restTemplate - PullRequest
0 голосов
/ 12 июня 2019

при вызове запроса API от службы я получаю следующую ошибку:

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"])

json, который я пытаюсь получить:

[ {
  "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"
    }
  }
} ]

функция, которая запрашивает APIВызов:

    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));
    }


Pojo класса:


@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);
    }
}```

Я попытался написать свой собственный JsonDeserialize, но это не сработало.Если я получу объект в getForEntity и самостоятельно десериализую его с помощью ObjectMapper, процесс, который будет выполняться поэтапно, в конечном итоге будет работать, но я ищу лучшее решение

1 Ответ

0 голосов
/ 12 июня 2019

Невозможно десериализовать экземпляр java.lang.String из Токен START_OBJECT;

Это исключение означает, что вы испортили отображение Джексона.

Мой личный совет для упрощения отладки: при работе со сложными структурами JSON вместо того, чтобы отображать всю структуру сразу, попробуйте сделать это шаг за шагом. Переходя с первого уровня, все глубже и глубже вниз медленно раскрывая JsonNodes.

Ошибка, скорее всего, здесь, потому что IgnoredCaseKey это не строка, а пользовательский объект. Попробуйте объявить пару ключей-значений attributes или a как JsonNode и идти вниз, чтобы найти причину ошибки.

Итак, ваш первый шаг - заменить это:

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

с этим:

@JsonProperty(ATTRIBUTES_PREFIX)
private JsonNode attributes;

Если это не вызывает каких-либо ошибок, проблема заключается в том, что Map<IgnoredCaseKey, Object> является неправильным типом для данного объекта JSON. Если это вызывает ошибки, проблема в другом месте.

Поскольку предоставленная вами структура JSON не точна, я не могу дать вам конкретный ответ, но надеюсь, что это направление поможет вам более эффективно устранять неполадки.

...