PreferencesDeserializer extends JsonDeserializer<Map<String, Serializable>> { @Override public Map<String, Serializable> deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException { Map<String, Serializable> result = new HashMap<>(); jsonParser.nextToken(); while (!JsonToken.END_OBJECT.equals(jsonParser.getCurrentToken())) { JsonToken currentToken = jsonParser.nextValue(); switch (currentToken) { case VALUE_NUMBER_INT: case VALUE_NUMBER_FLOAT: result.put(jsonParser.getCurrentName(), jsonParser.getNumberValue()); break; case VALUE_FALSE: case VALUE_TRUE: result.put(jsonParser.getCurrentName(), jsonParser.getValueAsBoolean()); break; case VALUE_STRING: result.put(jsonParser.getCurrentName(), jsonParser.getValueAsString()); break; case START_ARRAY: String key = jsonParser.getCurrentName(); ArrayList<Serializable> array = new ArrayList<>(); JsonToken nextValue = jsonParser.nextValue(); while (!JsonToken.END_ARRAY.equals(nextValue)) { switch (nextValue) { case VALUE_NUMBER_INT: case VALUE_NUMBER_FLOAT: array.add(jsonParser.getNumberValue()); break; case VALUE_FALSE: case VALUE_TRUE: array.add(jsonParser.getValueAsBoolean()); break; case VALUE_STRING: array.add(jsonParser.getValueAsString()); break; default: throw new JsonParseException( jsonParser, format( "Unexpected value in the nested array of the preference with key '%s'.", key)); } nextValue = jsonParser.nextValue(); } result.put(key, array.toArray()); break; default: throw new JsonParseException( jsonParser, format( "Unexpected value of the preference with key '%s'.", jsonParser.getCurrentName())); } jsonParser.nextToken(); } return result; }  @Override Map<String, Serializable> deserialize(JsonParser jsonParser, DeserializationContext ctxt);  }
@Test public void shouldParseSimpleTypesCorrectly() throws Exception { String json = "{" + "\"valid.string\": \"/usr/bin/value\"," + "\"valid.boolean\": false," + "\"valid.integer\": 777555888," + "\"valid.float\": 3.1415926," + "\"valid.string.array\": [\"foo\",\"bar\",\"baz\"]," + "\"valid.int.array\": [12,13,0]," + "\"valid.bool.array\": [true,false,false]" + "}"; final JsonParser parser = factory.createParser(json); Map<String, Serializable> result = preferencesDeserializer.deserialize(parser, ctxt); assertEquals(7, result.size()); assertEquals(result.get("valid.integer"), 777555888); assertEquals(result.get("valid.float"), 3.1415926); assertEquals(result.get("valid.boolean"), false); assertEquals(result.get("valid.string"), "/usr/bin/value"); assertEquals(result.get("valid.string.array"), new String[] {"foo", "bar", "baz"}); assertEquals(result.get("valid.int.array"), new int[] {12, 13, 0}); assertEquals(result.get("valid.bool.array"), new boolean[] {true, false, false}); }
@Test( expectedExceptions = JsonParseException.class, expectedExceptionsMessageRegExp = "Unexpected value of the preference with key 'invalid.object'.\n" + " at \\[Source: \\(String\\)\"\\{\"valid\\.string\": \"/usr/bin/value\",\"invalid\\.object\": \\{\"someobject\": true\\}\\}\"; line: 1, column: 54\\]") public void shouldThrowExceptionOnUnsupportedPreferenceValue() throws Exception { String json = "{" + "\"valid.string\": \"/usr/bin/value\"," + "\"invalid.object\": {\"someobject\": true}" + "}"; final JsonParser parser = factory.createParser(json); preferencesDeserializer.deserialize(parser, ctxt); }