json-flattener flattens nested JSON and unflattens it again, with a warning about what that means
A Java utility is designed to FLATTEN nested JSON objects and even more to UNFLATTEN them back
At a glance
- What is it?
- json-flattener is a Java library that converts nested JSON into a flat map of dotted and bracketed keys and can rebuild the nested structure from it, supporting Jackson, Gson, org.json and Jakarta through a json-base abstraction. It suits a developer moving JSON into a column store or an Elasticsearch index, and its own documentation says the flattened form must not be used as a security boundary.
- Who is it for?
- json-flattener fits a Java developer who needs a flat key space for a document store, a search index or a spreadsheet-shaped export and who may later need to rebuild the nesting. It does not fit a pipeline where the flattened form is validated or filtered and then unflattened, because the README states that is unsafe and that a value may end up at a path other than the one inspected.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 11 days ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What flattening looks like
The library is described as a Java utility designed to flatten nested JSON objects and even more to unflatten them back, and the transformation it performs is easy to read.
A nested document like this one.
{ "a":
{ "b": 1,
"c": null,
"d": [false, true]
},
"e": "f",
"g": 2.3
}Becomes this.
{ "a.b": 1,
"a.c": null,
"a.d[0]": false,
"a.d[1]": true,
"e": "f",
"g": 2.3
}The rules are the conventional ones: objects join their keys with a dot, array elements get a bracketed index, and scalars stay as they are. So the flattened key is a path expression rather than an opaque identifier, and that is what makes the unflatten direction possible at all.
Or it becomes a Java Map.
// {a.b=1, a.c=null, a.d[0]=false, a.d[1]=true, e=f, g=2.3}The library is published to Maven Central under groupId com.github.wnameless.json with artifactId json-flattener, and the README notes that Java 17 or above is required since v0.18.0, with v0.17.x for Java 8. The repository has no GitHub releases, and the last push was on 2026-10-12.
The three calls you actually need
The quick start is a JSON string in and either a Map or a flat JSON string out, with unflatten as the reverse.
Flattening to a Java Map.
Map<String, Object> flattenJson = JsonFlattener.flattenAsMap(json);
System.out.println(flattenJson);
// {a.b=1, a.c=null, a.d[0]=false, a.d[1]=true, e=f, g=2.3}Flattening to a JSON string.
String jsonStr = JsonFlattener.flatten(json);
System.out.println(jsonStr);
// {"a.b":1,"a.c":null,"a.d[0]":false,"a.d[1]":true,"e":"f","g":2.3}And unflattening from that string.
String nestedJson = JsonUnflattener.unflatten(jsonStr);
System.out.println(nestedJson);
// {"a":{"b":1,"c":null,"d":[false,true]},"e":"f","g":2.3}So there are two classes, one direction each, and the static entry points on them. The Map variant exists separately from the string variant, which is worth having because a Map is what you want when the flat form is destined for a document store or an index, and the string variant is what you want when you are transforming a payload in flight.
The unflatten direction also has a Map entry point, added in v0.11.0 according to the feature list, so the two directions are symmetric in their API surface.
The round trip is best effort, and the library says why
This is the section that decides whether you use the library, and the README is commendably direct about it.
JsonUnflattener is designed to undo what JsonFlattener does, however the round trip is a best effort rather than a guarantee. A flattened key is a textual encoding in which separators, brackets and quotes carry structural meaning, therefore some inputs cannot be encoded unambiguously and come back in a different shape.
Three known cases are listed. In FlattenMode.MONGODB, an object key which looks like an array index is restored as an array, because dot notation cannot tell the field "1" from the index 1, so {"a":{"1":2}} goes to {"a.1":2} and comes back as {"a":[null,2]}. Flattening and unflattening must share the same settings, since a different FlattenMode, separator, bracket pair or KeyTransformer produces a different structure, so {"a":{"b":1}} round-trips correctly with separator . but not with separator ,. And ignoreReservedCharacters() skips the key validation, which permits keys that cannot be parsed back, and it is a JsonFlattener option only.
The consequence is stated in the same paragraph as a hard rule. The flattened representation must not be used as a security boundary. Validating, filtering or deduplicating flattened keys and then unflattening the result is unsafe, because a value may end up at a path other than the one which was inspected. Such checks belong on the JSON structure itself or on the data after unflattening.
That is a specific and plausible attack shape: you inspect a flattened key to decide whether a value is permitted, then rebuild the structure and find the value somewhere else. If your pipeline filters on flat keys, this library is the wrong tool for the job.
Keys containing dots and brackets
The library handles the awkward case where a key itself contains a dot or a square bracket, and the way it does it is worth understanding.
// Supports JSON keys which contain dots or square brackets
String flattenedJsonWithDotKey = JsonFlattener.flatten("[{\"a.a.[\":1},2,{\"c\":[3,4]}]");
System.out.println(flattenedJsonWithDotKey);
// {"[0][\"a.a.[\"]":1,"[1]":2,"[2].c[0]":3,"[2].c[1]":4}
String nestedJsonWithDotKey = JsonUnflattener.unflatten(
"{\"[1][0]\":2,\"[0]\":1,\"[1][1]\":3,\"[2]\":4,\"[3][\\\"ab.c.[\\\"]\":5}");
System.out.println(nestedJsonWithDotKey);
// [1,[2,3],4,{"ab.c.[":5}]The mechanism is quoting. A key that contains a dot or a bracket gets wrapped in escaped quotes inside the flattened key, so the parser can tell the difference between a structural separator and a literal character in a key. The output in the example shows it, with the key rendered as "[0][\"a.a.[\"]".
That approach works, and it is why the feature list has an ignoreReservedCharacters() option added in v0.13.0: skipping the key validation lets a key through that the encoder cannot represent unambiguously, which is precisely the third case in the round trip warning. The option is a JsonFlattener option only, so there is no matching setting on the unflatten side.
Settings, factories and the JSON backend you choose
The feature list shows how the library has grown, and each row is a setting you can change.
The FlattenMode options are NORMAL and KEEP_ARRAYS from v0.2.0, plus KEEP_PRIMITIVE_ARRAYS added in v0.8.0 to keep all primitive JSON arrays, and MONGODB added in v0.4.0 for dot notation. The Separator option, also from v0.2.0, lets you change the character between object keys, and LeftAndRightBrackets from v0.3.0 lets you change the bracket pair.
PrintMode from v0.2.0 is MINIMAL or PRETTY, which decides whether the flat JSON string is compact or indented.
StringEscapePolicy has accumulated options across two versions, NORMAL and ALL_UNICODES from v0.2.0, then ALL, ALL_BUT_SLASH, ALL_BUT_UNICODE, ALL_BUT_SLASH_AND_UNICODE and DEFAULT from v0.6.0. CharSequenceTranslatorFactory from v0.5.0 lets you supply a customised StringEscapePolicy, and KeyTransformer from v0.4.0 manipulates keys before flattening.
Two factories, added in v0.14.0, exist so you can configure once and build repeatedly, which is the pattern a Spring application wants.
// Inside Spring configuration class
@Bean
public JsonFlattenerFactory jsonFlattenerFactory() {
// Changes the default PrintMode from MINIMAL to PRETTY
Consumer<JsonFlattener> configurer = jf -> jf.withPrintMode(PrintMode.PRETTY);
// Alters the default JsonCore from Jackson to GSON
JsonCore<?> jsonCore = new GsonJsonCore();
return new JsonFlattenerFactory(configurer, jsonCore);
}
// In any other Spring environment class
@Autowired
JsonFlattenerFactory jsonFlattenerFactory;
public void usageExamples(String json) {
JsonFlattener jf1 = jsonFlattenerFactory.build(json);
JsonFlattener jf2 = jsonFlattenerFactory.build(new StringReader(json));
JsonFlattener jf3 = jsonFlattenerFactory.build(new GsonJsonCore().parse(json));
}The three build overloads cover the three input shapes, a string, a Reader and an already-parsed value, and the Reader overload came with the Reader feature in v0.3.0.
Behind all of this sits the JSON backend choice, added in v0.12.0 as JsonCore, which lets you use Jackson, GSON, org.json or Jakarta through the json-base library, upgraded in v0.16.0 to support four major JSON implementations. Since v0.18.0 Jackson 3 has replaced Jackson 2, with Jackson 2 still supported through json-base. JsonValueBase, from v0.7.0, is the performance-oriented value type from that same library.
Where json-flattener is the wrong choice
Three cases argue against it.
The first is a pipeline that filters on flattened keys. The README says it directly: validating, filtering or deduplicating flattened keys and then unflattening the result is unsafe. If your requirement is a flat key space that you can safely authorise against, this representation is the wrong one, and you would need a scheme where the flat key carries its own authority rather than a path that can be reinterpreted.
The second is data with array-like object keys. The MongoDB mode example shows the problem: a field literally named 1 comes back as an array with a null in the first position. If your JSON can contain object keys that look like integers, the round trip is lossy in a way that changes the shape of the data rather than just its formatting.
The third is needing a stable, versioned contract for the flattened form. There are no GitHub releases for the project, and the behaviour depends on the settings you chose, so the flattened output is a function of the library version plus the FlattenMode, separator, bracket pair, KeyTransformer and escape policy. Sharing a flattened payload between two services means sharing all of that configuration, and the README warns that a mismatch produces a different structure rather than an error.
The alternative in the same direction is to use your JSON library's own flattening path expressions, which many document stores support natively, or to model the data as a schema rather than as a flat document. The difference in approach is that json-flattener gives you a general, reversible-ish transformation with a Java API and a choice of backend, while the document store route gives you a flat key space the database itself understands and indexes. For Elasticsearch or a MongoDB projection, the database's own dotted-path syntax is usually the better fit, and this library earns its place when you need the same transformation outside the database, for example to shape a JSON payload for an API or to export to a spreadsheet.
Editorial conclusion
json-flattener fits a Java developer who needs a flat key space for a document store, a search index or a spreadsheet-shaped export and who may later need to rebuild the nesting. It does not fit a pipeline where the flattened form is validated or filtered and then unflattened, because the README states that is unsafe and that a value may end up at a path other than the one inspected. Depend on `com.github.wnameless.json:json-flattener` with Java 17 or above, keep the flatten and unflatten settings identical since a different separator or FlattenMode produces a different structure, and treat the flattened keys as display data rather than as trusted paths.
Frequently asked questions
What does wnameless/json-flattener do?
It flattens nested JSON objects into a flat representation with dotted and bracketed keys, and unflattens them back. The flattening turns {"a":{"b":1}} into {"a.b":1}, and arrays become indexed keys such as a.d[0].
How do I add json-flattener to a Maven project?
Add the dependency with groupId com.github.wnameless.json and artifactId json-flattener, taking the version from the Maven Central badge in the README. Java 17 or above is required since v0.18.0, and v0.17.x is the line to use for Java 8.
Is the flatten and unflatten round trip lossless?
No, the README says it is a best effort rather than a guarantee. A key that looks like an array index in MONGODB mode comes back as an array element, and flattening and unflattening must share the same settings since a different separator, FlattenMode, bracket pair or KeyTransformer produces a different structure.
Can I use flattened JSON keys for access control?
No. The README states that the flattened representation must not be used as a security boundary, because validating, filtering or deduplicating flattened keys and then unflattening is unsafe, since a value may end up at a path other than the one that was inspected. Checks belong on the JSON structure or on the data after unflattening.
Which JSON libraries does json-flattener support?
Jackson 3, Jackson 2, Gson, org.json and Jakarta, through the json-base library, which was upgraded in v0.16.0 to support four major JSON implementations. The default JsonCore is Jackson, and GsonJsonCore and the other implementations can be substituted.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wnameless-json-flattener)Was this useful?