Java / Jackson: десериализовать JSON в класс с помощью HashMap - PullRequest
0 голосов
/ 05 сентября 2018

Я хочу десериализовать следующий ввод JSON:

{
  "key1": "value1",
  "key2": "value2"
}

в объект класса, содержащий хэш-карту:

public class ClassContainingMap {

  private Map<String, String> map = new HashMap<>();

  public Map<String, String> getMap() {
     return map;
  }

  public void setMap(Map<String, String> map) {
     this.map = map;
  }
}

При выполнении

ClassContainingMap m = objectMapper.readValue(json, ClassContaininMap.class);

Я получаю

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of test.ClassContainingMap: no Stri
ng-argument constructor/factory method to deserialize from String value ('key1')
 at [Source: "key1": "value1", "key2": "value2"; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
    at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012)
    at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:370)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:315)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1283)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:159)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:150)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2858)

Я обнаружил, что могу использовать другое направление (сериализацию) при аннотировании геттера с помощью @JsonValue, но до сих пор я не смог выяснить это для десериализации. Есть ли какой-нибудь простой (аннотация?) Способ добиться этого, без необходимости написания собственного десериализатора?

1 Ответ

0 голосов
/ 05 сентября 2018

Вы не предоставили пример того, как вы используете аннотацию @JsonValue, поэтому я мог что-то пропустить, но в любом случае.

При сериализации я думаю, что вы делаете что-то вроде:

ClassContainingMap ccm = new ClassContainingMap();
ccm.getMap().put("key1", "value1");
ccm.getMap().put("key2", "value2");

System.out.println(om.writeValueAsString(ccm)); 

Это сработает и даст следующий JSON:

{
    "map": {
        "key1":"value1",
        "key2":"value2",
    }
}

Но это не равно структуре JSON, которую вы хотите прочитать ClassContainingMap:

{
    "key1": "value1",
    "key2": "value2"
}

А именно, первые - это данные ClassContainingMap, а вторые - "только" Map, которые, я думаю, вы хотите заполнить внутри ClassContainingMap.

У вас есть два варианта для проверки, вы можете;

  1. используйте правильную структуру JSON в качестве источника, соответствующего ClassContainingMap
  2. просто десериализовать это на простую карту, например:

    Map map = om.readValue(i, Map.class);
    
  3. и, если возможно что-либо из вышеперечисленного, можно сделать это с помощью @JsonCreator

    @JsonCreator(mode=Mode.DELEGATING)
    public ClassContainingMap(@JsonProperty("map")Map<String,String> map) {
        this.map = map;
    }
    
    @JsonValue
    public Map<String, String> getMap() {
        return map;
    }
    

См. Дополнительную информацию о 3-м примере, например здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...