将 JSON 转换为排序的 JSON,其中包括嵌套节点中的 JSON 数组
Convert JSON to a sorted JSON which include JSONArrays in nested nodes
这里我想知道,如何将未排序的 JSON
字符串转换为包含多个 JSON
数组作为子元素的已排序 JSON
字符串。下面给出了示例未排序的 JSON
字符串,
{
"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"
}
}
预期输出如下,
{
"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",
}
有人可以帮我实现这个要求吗?
Java
中的JSON Object
可以用Map<String, Object>
表示,JSON Array
可以用List
、Set
、[=18表示=] 或任何其他 Collection
。最流行的图书馆如 Jackson and Gson can do that by default. For JSON Object
documentation 说:
An object is an unordered set of name/value pairs.
因此,大多数库默认情况下不关心顺序并使用无序 Map
实现。他们最多可以通过使用 LinkedHashMap
或任何其他类似的实现来保持 JSON
有效负载的顺序。但要强制排序,我们需要自定义配置。
对于 Gson
它可以是这样的:
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);
}
};
}
}
对于应用上面的 JSON
负载打印:
{
"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"
}
你可以试试 little json 库
和这段代码
(代码可以使用一个比较器实例更有效,您不需要制作对象的副本并在适当的地方对其进行排序。)
private static JsonValue deepsort(JsonValue value) {
if(value == null) return null;
else if(value.isLiteral()) return value.copy();
else if(value.isArray()) {
JsonArray newarray = JsonFactory.array();
for(JsonValue jsonValue : value.asArray().toList()) {
newarray.add(deepsort(jsonValue));
}
return newarray;
} else {
JsonObject newobject = JsonFactory.object();
List<JsonAttribute> attrs = value.asObject().toList();
Collections.sort(attrs, new Comparator<JsonAttribute>() {
@Override
public int compare(JsonAttribute o1, JsonAttribute o2) {
return o1.name().stringValue().compareTo(o2.name().stringValue());
}
});
for(JsonAttribute attr : attrs) {
newobject.add(attr.name().stringValue(), deepsort(attr.value()));
}
return newobject;
}
}
public static void main(String[] argv) {
String json = "{\n" +
" \"name\": \"John\",\n" +
" \"age\": 22,\n" +
" \"foods\": [{\n" +
" \"product\": \"apple\",\n" +
" \"price\": 100\n" +
" }, {\n" +
" \"fruit\": \"banana\",\n" +
" \"price\": 100\n" +
" }\n" +
" ],\n" +
"\n" +
" \"attributes\": {\n" +
" \"OBJECTID\": \"35\",\n" +
" \"FACILITYTYPE\": \"Pharmacy\",\n" +
" \"FACILITYSUBTYPE\": \"24 Hr Pharmacy\",\n" +
" \"COMMERCIALNAME_E\": \"SADD MAARAB PHARMACY\"\n" +
" }\n" +
"}";
JsonValue v = JsonParser.parse(json);
JsonValue newv = deepsort(v);
System.out.println(newv.toPrettyString(" "));
}
这里我想知道,如何将未排序的 JSON
字符串转换为包含多个 JSON
数组作为子元素的已排序 JSON
字符串。下面给出了示例未排序的 JSON
字符串,
{
"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"
}
}
预期输出如下,
{
"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",
}
有人可以帮我实现这个要求吗?
Java
中的JSON Object
可以用Map<String, Object>
表示,JSON Array
可以用List
、Set
、[=18表示=] 或任何其他 Collection
。最流行的图书馆如 Jackson and Gson can do that by default. For JSON Object
documentation 说:
An object is an unordered set of name/value pairs.
因此,大多数库默认情况下不关心顺序并使用无序 Map
实现。他们最多可以通过使用 LinkedHashMap
或任何其他类似的实现来保持 JSON
有效负载的顺序。但要强制排序,我们需要自定义配置。
对于 Gson
它可以是这样的:
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);
}
};
}
}
对于应用上面的 JSON
负载打印:
{
"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"
}
你可以试试 little json 库 和这段代码 (代码可以使用一个比较器实例更有效,您不需要制作对象的副本并在适当的地方对其进行排序。)
private static JsonValue deepsort(JsonValue value) {
if(value == null) return null;
else if(value.isLiteral()) return value.copy();
else if(value.isArray()) {
JsonArray newarray = JsonFactory.array();
for(JsonValue jsonValue : value.asArray().toList()) {
newarray.add(deepsort(jsonValue));
}
return newarray;
} else {
JsonObject newobject = JsonFactory.object();
List<JsonAttribute> attrs = value.asObject().toList();
Collections.sort(attrs, new Comparator<JsonAttribute>() {
@Override
public int compare(JsonAttribute o1, JsonAttribute o2) {
return o1.name().stringValue().compareTo(o2.name().stringValue());
}
});
for(JsonAttribute attr : attrs) {
newobject.add(attr.name().stringValue(), deepsort(attr.value()));
}
return newobject;
}
}
public static void main(String[] argv) {
String json = "{\n" +
" \"name\": \"John\",\n" +
" \"age\": 22,\n" +
" \"foods\": [{\n" +
" \"product\": \"apple\",\n" +
" \"price\": 100\n" +
" }, {\n" +
" \"fruit\": \"banana\",\n" +
" \"price\": 100\n" +
" }\n" +
" ],\n" +
"\n" +
" \"attributes\": {\n" +
" \"OBJECTID\": \"35\",\n" +
" \"FACILITYTYPE\": \"Pharmacy\",\n" +
" \"FACILITYSUBTYPE\": \"24 Hr Pharmacy\",\n" +
" \"COMMERCIALNAME_E\": \"SADD MAARAB PHARMACY\"\n" +
" }\n" +
"}";
JsonValue v = JsonParser.parse(json);
JsonValue newv = deepsort(v);
System.out.println(newv.toPrettyString(" "));
}