Jackson deserializacja mapy - LocalDate jako klucz

0

Mam taki problem.
Jest sobie JSON:

{
  "rates": {
    "2020-02-03": {
      "PLN": 4.2968
    },
    "2020-02-05": {
      "PLN": 4.2491
    },
    "2020-02-06": {
      "PLN": 4.2451
    },
    "2020-02-04": {
      "PLN": 4.2753
    },
    "2020-02-07": {
      "PLN": 4.2653
    }
  },
  "start_at": "2020-02-01",
  "base": "EUR",
  "end_at": "2020-02-08"
}

Robię sobie implementacje klasy Rates:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Rates {

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

  public Map<String, Object> getRates() {
    return rates;
  }

  public void setRates(Map<String, Object> rates) {
    this.rates = rates;
  }
}

I odpalam sprawdzić czy się deserializuje:

public class JsonTest {

  private static final LocalDate LOCAL_DATE = LocalDate.of(2020, 2, 3);
  private static final String LOCAL_DATE_STRING = "2020-02-03";
  private static final URL JSON_URL = Resources.getResource("rates.json");

  public static void main(String[] args) throws Exception {
    ObjectMapper objectMapper = getObjectMapper();
    var rates = objectMapper.readValue(JSON_URL, Rates.class);
    System.out.println(rates.getRates());

  }

  private static ObjectMapper getObjectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JSR310Module());
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    return objectMapper;
  }

  private static Map<LocalDate, String> testSerializationMap() {
    Map<LocalDate, String> testMap = new HashMap<>();
    testMap.put(LocalDate.of(2016, 4, 29), "Affinity");
    return testMap;
  }
}

Działa, wyświetla się elegancko:

{2020-02-03={PLN=4.2968}, 2020-02-05={PLN=4.2491}, 2020-02-06={PLN=4.2451}, 2020-02-04={PLN=4.2753}, 2020-02-07={PLN=4.2653}}

Jeśli jednak zamienie String na LocalDate to dostaje coś takiego:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot find a (Map) Key deserializer for type [simple type, class java.time.LocalDate]
 at [Source: (URL); line: 1, column: 1]

Co z tym zrobić? Dodam że serializacja z kolei działa poprawnie, i jak mam np. Map<LocalDate, String> to działa ok:

public static void main(String[] args) throws Exception {
    ObjectMapper objectMapper = getObjectMapper();
    var json = objectMapper.writeValueAsString(testSerializationMap());
    System.out.println(json);
  }

 // coś tam coś tam

 private static Map<LocalDate, String> testSerializationMap() {
    Map<LocalDate, String> testMap = new HashMap<>();
    testMap.put(LocalDate.of(2016, 4, 29), "Affinity");
    return testMap;
  }

Wypluwając:

{"2016-04-29":"Affinity"}
2

Pierwszy wynik z Googla: https://stackoverflow.com/questions/6371092/can-not-find-a-map-key-deserializer-for-type-simple-type-class-com-comcast-i
Czyli musisz dopisać swój deserializer do klucza mapy, bo wygląda na to, że JSR310Module nie wspiera takiego feature

Sprawdź też czy jest różnica w używaniu JavaTimeModule zamiast JSR310Module

0

No faktycznie, nie tak szukałem jak trzeba :(

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