json-flattener: [Bug] flattenAsMap produces escaped field names for field names that contain dot

Here’s a code sample to demonstrate the issue.

public static void main(String[] args) throws Exception {
	final ObjectMapper mapper = new ObjectMapper();
	/*
	 * The input is just a simple json object { "a.b": 1 }
	 */
	final String jsonString = "{ \"a.b\": 1 }";
	final String flattenedString = JsonFlattener.flatten(jsonString);
	/*
	 * The following line prints
	 * {"[\"a.b\"]":1}
	 *
	 * No problem here.
	 */
	System.out.println(flattenedString);
	/*
	 * Print the only field name in the flattened json. It prints
	 * ["a.b"]
	 *
	 * No problem here either.
	 */
	System.out.println(mapper.readTree(flattenedString).fieldNames().next());
	final Map<String, Object> flattenedMap = JsonFlattener.flattenAsMap(jsonString);
	/*
	 * Print the only field name in the flattened map. It prints
	 * [\"a.b\"]
	 *
	 * And here's the problem. For some reason the quotes in the field name in the
	 * flattened map got unnecessarily escaped.
	 */
	System.out.println(flattenedMap.keySet().iterator().next());
	/*
	 * Just to confirm this, I'm parsing the map into json and printing the json.
	 * It prints
	 * {"[\\\"a.b\\\"]":1}
	 *
	 * So yes, the flattened map field name got unnecessarily escaped
	 */
	System.out.println(mapper.writeValueAsString(mapper.valueToTree(flattenedMap)));
}

So the gist of the issue is that, when you have a field name with a dot, the flatten method flattens things correctly, but flattenAsMap produces a Map with field names that got unnecessarily (and incorrectly) escaped.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 19 (6 by maintainers)

Most upvoted comments

(Outdated)

@jpomykala I think you must be doing something wrong with your JSON input. Here’s my code sample and it does give me the correct result:

public static void main(String[] args) {
	final String jsonStr = "{\n" +
			"                    \"login\": {\n" +
			"                        \"page\": {\n" +
			"                            \"name\": {\n" +
			"                                \"first\": \"first name\",\n" +
			"                                \"last\": \"last name\"\n" +
			"                            },\n" +
			"                            \"address\" : {\n" +
			"                                \"line_1\": \"Login page address line_1\",\n" +
			"                                \"line_2\": \"Login page address line_2\"\n" +
			"                            }\n" +
			"                        }\n" +
			"                    }\n" +
			"                }";
	final Map<String, Object> m = new JsonFlattener(jsonStr).withSeparator('.').flattenAsMap();
	System.out.println(m);
	// prints {"login.page.name.first":"first name","login.page.name.last":"last name","login.page.address.line_1":"Login page address line_1","login.page.address.line_2":"Login page address line_2"}
	System.out.println(m.keySet());
	// prints [login.page.name.first, login.page.name.last, login.page.address.line_1, login.page.address.line_2]
}

Hi @zubair-farooqui

Dot(.) is a reserved word which is used to be separators in keys of the flattened JSON. If you wan to change the default separator setting, you simply apply #withSeparator(‘*’) (you can change * to any character you want to use) to either JsonFlattener or JsonUnflattener, in doing so, your problem should be solved.

@wnameless I am facing a similar issue. Consider following JSON: { "test": 1, "west.": 2 } When we apply flattenAsMap on the above JSON then the MAP which is created is like: image

If there is a dot (“.”) in the key then an additional “[""]” is added to the key. The key “west.” becomes ["west."] which is wrong.