Как получить ключ от JSON и сохранить порядок - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть JSON с некоторыми key-value парами.Мне нужно подобрать по имени и обработать его значение по-разному.Порядок процесса должен быть в том же порядке, что и ключи, перечисленные в JSON (JSON неизвестен, только знает, что он будет иметь некоторый ключ и соответствующее значение, поэтому не может знать порядок за пределами 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 (не хочу добавлять зависимость javax.json:javax.json-api)

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

org.json.JSONObject для внутреннего использования HashMap.Они даже добавили некоторые комментарии к нему:

HashMap используется специально для того, чтобы гарантировать, что элементы не упорядочены в спецификации.JSON имеет тенденцию быть переносимым форматом передачи, который позволяет реализациям контейнера переупорядочивать свои элементы для более быстрого поиска элементов на основе ассоциативного доступа.Следовательно, реализация не должна полагаться на порядок элемента .

Использование Gson.Он использует com.google.gson.internal.LinkedTreeMap реализацию для Map.Из документации:

Карта сопоставимых ключей к значениям.В отличие от TreeMap, этот класс использует порядок вставки для порядка итерации.Порядок сравнения используется только в качестве оптимизации для эффективной вставки и удаления.
Эта реализация была получена из класса TreeMap Android 4.1.

Итак, для ниже 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

Обратите внимание, что key и Field1 находятся в разном порядке в abc иrgj объектов.

0 голосов
/ 13 марта 2019

Еще одна вещь, которую вы можете сделать, это обратиться к 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;
    }
}
0 голосов
/ 27 февраля 2019

вы можете использовать jsonparser, а не jsonreader, чтобы контролировать поток событий.См. https://docs.oracle.com/javaee/7/api/javax/json/stream/JsonParser.html

Обратите внимание, что ваш вопрос не относится ни к котлину, ни к gson.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...