如何从json获取密钥并保留顺序

时间:2019-02-27 16:49:58

标签: json kotlin gson

我有一个JSON和一些key-value对。我需要按名称选择并以不同的方式处理其价值。该过程的顺序应与JSON中列出的键的顺序相同(JSON是未知的,仅知道它将具有一些键和对应的值,因此无法知道{之外的顺序{1}}。

简化的示例用法:

JSON

问题是String jsonData = "{key1:{some other data}, key2:{sub-key:sub-value}}"; val jsonObject = JSONObject(jsonData) val names = jsonObject.keys() if (names.hasNext()) { val key = names.next() val valueJson = jsonData.optString(key) val gson = Gson() val resultList = ArrayList<Data> () // result should keep the order as the keys in the json if (key == "key1") { val parsedResult = gson.fromJson <POJO_1> (valueJson, POJO_1::class.java) resultList.add(processDataFromKey1(parsedResult)) } else if (key == "key2") { val parsedResult = gson.fromJson <POJO_2> (valueJson, POJO_2::class.java) resultList.add(processDataFromKey2(parsedResult)) } } 键的顺序是jsonObject.keys()

那么如何保留undefined字符串中键的顺序(不想添加依赖项JSON

3 个答案:

答案 0 :(得分:1)

您可以使用jsonparser而不是jsonreader来控制事件流。 参见https://docs.oracle.com/javaee/7/api/javax/json/stream/JsonParser.html

请注意,您的问题既不是Kotlin也不是gson。

答案 1 :(得分:1)

org.json.JSONObject在内部使用HashMap。他们甚至在其中添加了一些评论:

  

HashMap专门用于确保元素不被   规范。 JSON通常是一种可移植的传输格式,   允许容器实现为   基于关联访问的更快元素检索。因此,   实施不得依赖于项目的顺序

使用Gson。它对com.google.gson.internal.LinkedTreeMap使用Map实现。从它的文档中:

  

可比较键到值的映射。与TreeMap不同,此类   将插入顺序用于迭代顺序。仅比较顺序   用于优化有效插入和删除操作。
  此实现源自Android 4.1的TreeMap类。

因此,对于JSON以下的payload

{
  "status": "status",
  "date": "01/10/2019",
  "abc": {
    "Field1": "value1",
    "key": "value2"
  },
  "rgj": {
    "key": "value2",
    "Field1": "value3"
  },
  "name": "Rick"
}

此示例应用程序:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.Map;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();
        Gson gson = new GsonBuilder().create();

        Type type = new TypeToken<Map<String, Object>>() {
        }.getType();
        Map<String, Object> map = gson.fromJson(new FileReader(jsonFile), type);
        map.forEach((k, v) -> {
            if (v instanceof Map) {
                System.out.println(k);
                ((Map) v).forEach((k1, v1) -> System.out.println("   " + k1 + " => " + v1));
            } else {
                System.out.println(k + " => " + v);
            }
        });
    }
}

打印:

status => status
date => 01/10/2019
abc
   Field1 => value1
   key => value2
rgj
   key => value2
   Field1 => value3
name => Rick

请注意,keyField1对象中的abcrgj的顺序不同。

答案 2 :(得分:0)

您可以做的另一件事是在示例中引用String jsonData并重建顺序。

类似的东西:

JSONObject json = new JSONObject(jsonData);
Iterator<String> keys = json.keys();
List<KeyOrder> ordering = new ArrayList();
while(keys.hasNext()) {
    String key = keys.next();
    int loc = jsonData.indexOf('"' + key + '"');
    ordering.add(new KeyOrder(loc, key));
}
Collections.sort(ordering);
for(KeyOrder order: ordering) {
    Object value = json.get(order.getKey());
    // process the key and value
}

public class KeyOrder implements Comparable<KeyOrder> {
    private int order;
    private String key;

    public KeyOrder(int order, String key) {
        this.order = order;
        this.key = key;
    }

    @Override
    public int compareTo(KeyOrder o) {
        return order - o.getOrder();
    }

    private int getOrder() {
        return order;
    }

    public String getKey() {
        return key;
    }
}