将 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可以用ListSet、[=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("  "));
    }