diff --git a/src/main/java/apoc/map/Maps.java b/src/main/java/apoc/map/Maps.java index 8461b99b..c842e954 100644 --- a/src/main/java/apoc/map/Maps.java +++ b/src/main/java/apoc/map/Maps.java @@ -295,6 +295,36 @@ private void flattenMapRecursively(Map flattenedMap, Map unflatten( @Name( "flatMap" ) Map flatMap ) { + Map unflattenedMap = new HashMap<>(); + + for ( Map.Entry entry : flatMap.entrySet() ) { + String[] keys = entry.getKey().split( "\\." ); + + Map current = unflattenedMap; + + for ( int i = 0; i < keys.length - 1; ++i ) { + String key = keys[i]; + + Object temp = current.get( key ); + if ( temp == null ) { + Map next = new HashMap<>(); + current.put( key, next ); + current = next; + continue; + } + + current = (Map) temp; + } + + current.put( keys[keys.length - 1], entry.getValue() ); + } + + return unflattenedMap; + } + @UserFunction @Description("apoc.map.sortedProperties(map, ignoreCase:true) - returns a list of key/value list pairs, with pairs sorted by keys alphabetically, with optional case sensitivity") public List> sortedProperties(@Name("map") Map map, @Name(value="ignoreCase", defaultValue = "true") boolean ignoreCase) { diff --git a/src/test/java/apoc/map/MapsTest.java b/src/test/java/apoc/map/MapsTest.java index 29d0dc7b..02291650 100644 --- a/src/test/java/apoc/map/MapsTest.java +++ b/src/test/java/apoc/map/MapsTest.java @@ -7,6 +7,7 @@ import org.neo4j.graphdb.Node; import org.neo4j.test.rule.DbmsRule; import org.neo4j.test.rule.ImpermanentDbmsRule; +import org.neo4j.graphdb.QueryExecutionException; import java.util.List; import java.util.Map; @@ -317,6 +318,21 @@ public void testFlattenWithDelimiter() { }); } + @SuppressWarnings("unchecked") + public void testUnflatten() { + Map flatMap = map( "string", "value", "int", 10, "nested.anotherkey", "anotherValue", "nested.nested.somekey", "someValue", "nested.nested.somenumeric", 123 ); + TestUtil.testCall( db, "RETURN apoc.map.unflatten($map) AS value", map( "map", flatMap ), (r) -> { + Map resultMap = (Map)r.get( "value" ); + assertEquals( map( "string", "value", "int", 10, "nested", map( "anotherkey", "anotherValue", "nested", map( "somekey", "someValue", "somenumeric", 123 ) ) ), resultMap ); + } ); + } + + @Test (expected = QueryExecutionException.class) + public void testUnflattenConflictingKeys() { + Map flatMap = map( "key", "value", "key.nested", "anotherValue" ); + TestUtil.testCall( db, "RETURN apoc.map.unflatten($map) AS value", map( "map", flatMap ), (r) -> {} ); + } + @Test public void testSortedProperties() { TestUtil.testCall(db, "WITH {b:8, d:3, a:2, E: 12, C:9} as map RETURN apoc.map.sortedProperties(map, false) AS sortedProperties", (r) -> {