【问题标题】:Convert JSON to a sorted JSON which include JSONArrays in nested nodes将 JSON 转换为在嵌套节点中包含 JSONArrays 的排序 JSON
【发布时间】:2019-11-27 17:59:15
【问题描述】:

在这里我想知道,如何将未排序的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",
}

有人可以帮我实现这个要求吗?

【问题讨论】:

  • 您是否仅限于某些特定的 JSON 库?例如,如果您使用的是 jackson,这可能会让您感兴趣 logicbig.com/tutorials/misc/jackson/…(参见关于 @JsonPropertyOrder(alphabetic = true) 的部分)
  • 所以您没有对数据进行任何修改,只是希望它打印得很好?如果键的顺序很重要并改变了你的功能,那么你就会遇到更大的问题。

标签: java json string key-value alphabetical


【解决方案1】:

Java 中的JSON Object 可以用Map<String, Object> 表示,JSON Array 可以用ListSetarray[] 或任何其他Collection 表示。最流行的库,如 JacksonGson 默认可以做到这一点。对于JSON Object documentation 说:

对象是一组无序的名称/值对。

因此,大多数库默认情况下不关心顺序,而是使用无序的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"
}

【讨论】:

    【解决方案2】:

    你可以试试小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("  "));
        }
    

    【讨论】:

      猜你喜欢
      • 2018-01-03
      • 2021-08-19
      • 2022-07-08
      • 2019-04-04
      • 2017-06-01
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多