«1. Введение
В этом руководстве мы рассмотрим несколько подходов к повторению JSONObject, простого представления JSON для Java.
Мы начнем с простого решения, а затем рассмотрим что-то более надежное.
2. Итерация по JSONObject
Давайте начнем с простого случая итерации JSON пар имя-значение:
{
"name": "Cake",
"cakeId": "0001",
"cakeShape": "Heart"
}
Для этого мы можем просто перебрать ключи, используя метод keys() :
void handleJSONObject(JSONObject jsonObject) {
jsonObject.keys().forEachRemaining(key -> {
Object value = jsonObject.get(key);
logger.info("Key: {0}\tValue: {1}", key, value);
}
}
И наш вывод будет таким:
Key: name Value: Cake
Key: cakeId Value: 0001
Key: cakeShape Value: Heart
3. Обход объекта JSON
Но допустим, что у нас есть более сложная структура:
{
"batters": [
{
"type": "Regular",
"id": "1001"
},
{
"type": "Chocolate",
"id": "1002"
},
{
"type": "BlueBerry",
"id": "1003"
}
],
"name": "Cake",
"cakeId": "0001"
}
Что означает перебор объекта ключи в данном случае?
Давайте посмотрим, что даст нам наш наивный подход с ключами():
Key: batters Value: [{"type":"Regular","id":"1001"},{"type":"Chocolate","id":"1002"},
{"type":"BlueBerry","id":"1003"}]
Key: name Value: Cake
Key: cakeId Value: 0001
Возможно, это не так полезно. Похоже, что в данном случае нам нужна не итерация, а обход.
Обход через JSONObject отличается от итерации по набору ключей JSONObject.
Для этого нам нужно также проверить тип значения. Давайте представим, что мы делаем это в отдельном методе:
void handleValue(Object value) {
if (value instanceof JSONObject) {
handleJSONObject((JSONObject) value);
} else if (value instanceof JSONArray) {
handleJSONArray((JSONArray) value);
} else {
logger.info("Value: {0}", value);
}
}
Тогда наш подход все еще довольно похож:
void handleJSONObject(JSONObject jsonObject) {
jsonObject.keys().forEachRemaining(key -> {
Object value = jsonObject.get(key);
logger.info("Key: {0}", key);
handleValue(value);
});
}
Единственное, что нам нужно подумать о том, как обрабатывать массивы.
4. Обход JSONArray
Давайте попробуем сохранить аналогичный подход с использованием итератора. Однако вместо вызова keys() мы будем вызывать iterator():
void handleJSONArray(JSONArray jsonArray) {
jsonArray.iterator().forEachRemaining(element -> {
handleValue(element)
});
}
Теперь это решение является ограничивающим, поскольку мы комбинируем обход с действием, которое хотим выполнить. Распространенным подходом к их разделению является использование шаблона «Посетитель».
5. Заключение
В этой статье мы рассмотрели способ перебора JSONObject для простых пар имя-значение, проблему, связанную со сложными структурами, и технику обхода для ее решения.
Конечно, это был метод обхода в глубину, но мы могли бы сделать обход в ширину аналогичным образом.
Полный код примера доступен на Github.