Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions ContainerConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.*;

public class ContainerConverter {

/*
* Purpose: Take a multidimensional container and convert it into a single
* dimension container.
*/
public static JSONObject toSingleDimension(JSONObject container) {
JSONObject oneDContainer = new JSONObject(); // the converted container

recurse(oneDContainer, container, "");
return oneDContainer;
}

/*
* Purpose: Traverse the multidimensional container, build the various paths,
* and pair them with their respective values
*/
private static void recurse(JSONObject oneDContainer, JSONObject jsonObject, String prefix) {
Iterator<String> keys = jsonObject.keys();

while(keys.hasNext()) {
String key = keys.next();
// Continue down the branch if value is another object
if(jsonObject.get(key) instanceof JSONObject) {
recurse(oneDContainer, (JSONObject)jsonObject.get(key), prefix+"/"+key);
} else {
// Continue to elements if value is an array
if(jsonObject.get(key) instanceof JSONArray) {
handleArray(oneDContainer, jsonObject.getJSONArray(key), prefix+"/"+key);
}
// Add final key string and value to the 1D container
else {
oneDContainer.put(prefix.substring(1)+"/"+key, jsonObject.get(key)); // substr to remove first "/"
}
}
}
}

/*
* Purpose: Handle the base case for traversing in which the value is an array instead of
* a single element. Used by function 'recurse'.
*/
private static void handleArray(JSONObject oneDContainer, JSONArray jsonArray, String prefix) {
String correctedPrefix = prefix.substring(1) + "/"; // remove first "/" and add final one
for(int i=0; i<jsonArray.length(); i++) {
oneDContainer.put(correctedPrefix+i, jsonArray.get(i));
}
}

/*
* Purpose: Take a single dimensional container and turn it into a multidimensional container.
*/
public static JSONObject toMultiDimension(JSONObject oneDContainer) {
JSONObject multiDContainer = new JSONObject(); // the converted container
Iterator<String> paths = oneDContainer.keys();

// go through all of the key paths
while(paths.hasNext() ) {
String path = paths.next();
String[] keyAndSubpath = getFirstKey(path);
createObjectFromPath(oneDContainer, multiDContainer, path, keyAndSubpath);

}

return multiDContainer;
}

/*
* Purpose: Take a path key string and create a new or append to an existing multidimensional container based
* off of it.
*/
private static void createObjectFromPath(JSONObject originalContainer, JSONObject object, String originalPath, String[] keyAndSubpath) {
// create an object with a key and a single element value if we're at the end of the path
if(keyAndSubpath[1].equals("")) {
object.put(keyAndSubpath[0], originalContainer.get(originalPath));
}
// find/create an object with a key and an array value if we're at the second to the end
// and the last directory is an index value
else if(keyAndSubpath[1].matches("\\d+")) {
JSONArray array;
if(object.has(keyAndSubpath[0])) {
array = (JSONArray)object.get(keyAndSubpath[0]);
} else {
array = new JSONArray();
object.put(keyAndSubpath[0], array);
}
array.put(originalContainer.get(originalPath));
}
// find existing child object or create a new one and continue down
else {
if(object.has(keyAndSubpath[0])) {
createObjectFromPath(originalContainer, object.getJSONObject(keyAndSubpath[0]),
originalPath, getFirstKey(keyAndSubpath[1]));
} else {
JSONObject childObject = new JSONObject();
createObjectFromPath(originalContainer, childObject,
originalPath, getFirstKey(keyAndSubpath[1]));
object.put(keyAndSubpath[0], childObject);
}
}
}

private static String[] getFirstKey(String path) {
String[] result = {path, ""};

// get the first key from the path
for(int i=0; i<path.length()-1; i++) {
if(path.charAt(i+1) == '/') {
result[0] = path.substring(0, i+1);
result[1] = path.substring(i+2);
break;
}
}

return result;
}
}
7 changes: 7 additions & 0 deletions READMEsubmission.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Both functions are written in Java. The functions are found in ContainerConverter.java. The function for the first part is called toSingleDimension().
The function for the second part is called toMultiDimension(). There is also a JUnit test file called TestContainerConverter.java that
utilizes the example case.

The functions rely on a JSON library for Java which can be found here: https://github.com/stleary/JSON-java
I have also pushed the version of the library I am using for these functions.
103 changes: 103 additions & 0 deletions TestContainerConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import static org.junit.jupiter.api.Assertions.*;

import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;

class TestContainerConverter {

/* Test for turning a multidimension container into a single dimension one*/
@Test
void testToSingleExample() {
JSONObject start = new JSONObject();
JSONObject one = new JSONObject();
JSONObject eight = new JSONObject();
JSONObject nine = new JSONObject();
JSONArray four = new JSONArray();
JSONObject result;

// setup the original container
four.put(5);
four.put(6);
four.put(7);

one.put("two", 3);
one.put("four", four);

nine.put("ten", 11);

eight.put("nine", nine);

start.put("one", one);
start.put("eight", eight);

result = ContainerConverter.toSingleDimension(start);

// check that all keys were created properly
assertEquals(5, result.length());
assert(result.has("one/two"));
assert(result.has("one/four/0"));
assert(result.has("one/four/1"));
assert(result.has("one/four/2"));
assert(result.has("eight/nine/ten"));

//check that values are correct and assigned to correct keys
assertEquals(3, result.get("one/two"));
assertEquals(5, result.get("one/four/0"));
assertEquals(6, result.get("one/four/1"));
assertEquals(7, result.get("one/four/2"));
assertEquals(11, result.get("eight/nine/ten"));
}

/* Test for turning a single dimension container into a multidimension one */
@Test
void testToMultiExample() {
JSONObject start = new JSONObject();
JSONObject result;

// setup the original container
start.put("eight/nine/ten", 11);
start.put("one/four/0", 5);
start.put("one/two", 3);
start.put("one/four/1", 6);
start.put("one/four/2", 7);

result = ContainerConverter.toMultiDimension(start);

// check that 1st level keys were created properly
assertEquals(2, result.length());
assert(result.has("one"));
assert(result.has("eight"));

// check that 1st level values are correct and assigned to correct keys
assert(result.get("one") instanceof JSONObject);
assert(result.get("eight") instanceof JSONObject);

//check that 2nd level keys were created properly
JSONObject one = result.getJSONObject("one");
JSONObject eight = result.getJSONObject("eight");

assertEquals(2, one.length());
assertEquals(1, eight.length());
assert(one.has("two"));
assert(one.has("four"));
assert(eight.has("nine"));

//check that 2nd level values are correct and assigned to correct keys
assertEquals(3, one.get("two"));
assert(one.get("four") instanceof JSONArray);
assert(eight.get("nine") instanceof JSONObject);
assertEquals(5, one.getJSONArray("four").get(0));
assertEquals(6, one.getJSONArray("four").get(1));
assertEquals(7, one.getJSONArray("four").get(2));

// check that 3rd level key is created properly
JSONObject nine = eight.getJSONObject("nine");

assertEquals(1, nine.length());
assert(nine.has("ten"));

// check that 3rd level value is correct and assigned to correct key
assertEquals(11, nine.get("ten"));
}
}
Binary file added json-20201115.jar
Binary file not shown.