javajsonjacksonpojo

Defining POJO with variable key


I am trying to convert a JSON to POJO wherein the key is variable. For example: Berlin, Paris in below examples:

{
  "Berlin": {
    "en-US": {
      "displayName": "US",
      "supportedLanguage": [
        "US"
      ],
      "FullExample": "Hello us"
    },
    "en-CA": {
      "displayName": "CA",
      "supportedLanguage": [
        "CA"
      ],
      "FullExample": "Hello CA"
    }
  },
  "Paris": {
    "en-US": {
      "displayName": "US",
      "supportedLanguage": [
        "US"
      ],
      "FullExample": "Hello US"
    },
    "en-CA": {
      "displayName": "CA",
      "supportedLanguage": [
        "CA"
      ],
      "FullExample": "Hello CA"
    }
  }
}

For everything inside the variable keys(Berlin, Paris) for example:

    "en-US": {
      "displayName": "US",
      "supportedLanguage": [
        "US"
      ],
      "FullExample": "Hello us"
    },
    "en-CA": {
      "displayName": "CA",
      "supportedLanguage": [
        "CA"
      ],
      "FullExample": "Hello CA"
    }

I defined the class as below:

class CityData {

Map <String, LanguageData> locale;
}

class LanguageData {
String displayName;
List<String> supportedLanguage;
String fullExample;
}

And finally to accomodate for variableKeys, I define a new object as follows:

class City {

Map<String, CityData> city;

}

However, I get the following error:

Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Berlin" , not marked as ignorable (0 known properties: ])

How do I get the variable keys to be stored in POJO ? It is something essential, so I would want to retrieve it via jackson objectmapper readValue.


Solution

  • You need to parse your data as Map<String, CityData>, not as an object containing a Map property. Your root level is the Map.

    Map<String, CityData> parsed = objectMapper.readValue(
      input,
      new TypeReference<Map<String, CityData>>() {});
    

    With your type City, you could parse JSON with the following structure:

    {
      "city": {
        "Berlin": { ... },
        "Paris": { ... }
      }
    }
    

    Which has your actual JSON nested under the key "city" (Map<String, CityData> city).