Here I would like to know that, how to convert a un-sorted JSON
string to a sorted JSON
string which include multiple JSON
arrays as child elements. The sample un-sorted JSON
string is given below,
{
"name": "John",
"age": 22,
"foods": [{
"product": "apple",
"price": 100
}, {
"fruit": "banana",
"price": 100
}
],
"attributes": {
"OBJECTID": "35",
"FACILITYTYPE": "Pharmacy",
"FACILITYSUBTYPE": "24 Hr Pharmacy",
"COMMERCIALNAME_E": "SADD MAARAB PHARMACY"
}
}
Expected output is as follows,
{
"age": 22,
"attributes": {
"COMMERCIALNAME_E": "SADD MAARAB PHARMACY",
"FACILITYSUBTYPE": "24 Hr Pharmacy",
"FACILITYTYPE": "Pharmacy",
"OBJECTID": "35"
},
"foods": [{
"price": 100m
"product": "apple"
}, {
"fruit": "banana",
"price": 100
}
],
"name": "John",
}
Can someone help me to achieve this requirement?
JSON Object
in Java
can be represented by Map<String, Object>
and JSON Array
can be represented by List
, Set
, array[]
or any other Collection
. Most popular libraries like Jackson and Gson can do that by default. For JSON Object
documentation says:
An object is an unordered set of name/value pairs.
So, most libraries by default do not take care about order and used unordered Map
implementations. At most they can keep order from JSON
payload by using LinkedHashMap
or any other similar implementation. But to force order we need to customise configuration.
For Gson
it can look like this:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.registerTypeAdapterFactory(new TreeMapTypeAdapterFactory())
.create();
Map root = gson.fromJson(new FileReader(jsonFile), Map.class);
System.out.println(gson.toJson(root));
}
}
class TreeMapTypeAdapterFactory implements TypeAdapterFactory {
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (Map.class.isAssignableFrom(type.getRawType())) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
return createCustomTypeAdapter(delegate);
}
return null;
}
private <T> TypeAdapter<T> createCustomTypeAdapter(TypeAdapter<T> delegate) {
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
Map map = (Map) value;
delegate.write(out, (T) new TreeMap(map));
}
@Override
public T read(JsonReader in) throws IOException {
return delegate.read(in);
}
};
}
}
For JSON
payload above app prints:
{
"age": 22.0,
"attributes": {
"COMMERCIALNAME_E": "SADD MAARAB PHARMACY",
"FACILITYSUBTYPE": "24 Hr Pharmacy",
"FACILITYTYPE": "Pharmacy",
"OBJECTID": "35"
},
"foods": [
{
"price": 100.0,
"product": "apple"
},
{
"fruit": "banana",
"price": 100.0
}
],
"name": "John"
}