Json Разбор в Java Получить значения из массива, предоставив ключи только один раз? - PullRequest
0 голосов
/ 29 апреля 2020

Например, следующее JSON

[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  },
  {
    "id": 2,
    "name": "Ervin Howell",
    "username": "Antonette",
    "email": "Shanna@melissa.tv",
    "address": {
      "street": "Victor Plains",
      "suite": "Suite 879",
      "city": "Wisokyburgh",
      "zipcode": "90566-7771",
      "geo": {
        "lat": "-43.9509",
        "lng": "-34.4618"
      }
    },
    "phone": "010-692-6593 x09125",
    "website": "anastasia.net",
    "company": {
      "name": "Deckow-Crist",
      "catchPhrase": "Proactive didactic contingency",
      "bs": "synergize scalable supply-chains"
    }
  }
]

Как мы можем получить ключи только один раз, когда имеем дело с большим количеством массивов. Например, Give id дает ключи всех массивов снова и снова. Я просто хочу получить идентификатор только один раз, и когда пользователь вводит идентификатор, он дает значения идентификатора во всем массиве.

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ValueNode;
import java.io.File;
import java.io.IOException;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        File file=new File("src/data.json");
        ObjectMapper mapper=new ObjectMapper();
        Scanner scanner=new Scanner(System.in);
        try {

            LinkedHashMap<String,String> map= new LinkedHashMap<String, String>();
            JsonNode node =mapper.readTree(file);
            getKeys("",node, map);
            for (Map.Entry<String, String> entry : map.entrySet()) {
                System.out.println(entry.getKey() );
            }
            System.out.println();
            while (true) {
                System.out.println(map.get(scanner.next()));

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void getKeys(String currentpath,JsonNode node,LinkedHashMap map){
        if(node.isObject()){
            ObjectNode objectNode=(ObjectNode) node;
            Iterator<Map.Entry<String, JsonNode>> it=objectNode.fields();
            String prefix=currentpath.isEmpty()?"":currentpath+".";
            while (it.hasNext()){
                SortedMap.Entry<String,JsonNode> iter=it.next();
                getKeys(prefix+iter.getKey(),iter.getValue(),map);
            }
        }else if (node.isArray()){
            ArrayNode arrayNode=(ArrayNode) node;
            for(int i=0; i<arrayNode.size(); i++){
                getKeys(currentpath+i,arrayNode.get(i),map);
            }
        }
        else if(node.isValueNode()) {
            ValueNode valueNode=(ValueNode) node;
            map.put(currentpath,valueNode.asText());
        }
    }
}

Ниже приведен результат кода и ожидаемый результат

key:0.address.city
Key:0.address.geo.lng
Key:0.name
Key:0.username

key:1.address.city
Key:1.address.geo.lng
Key:1.name
Key:1.username

output should like this with out index of array

name
username
address.city
address.geo.lng

 Graham
 Bret
 Gwenborough
 81.1496

 aham
 ret
 borough
 80.1496

------------------
Thanks is advance.

1 Ответ

1 голос
/ 29 апреля 2020

Вы можете создать Map<String, List<String>>, чтобы сопоставить ключ со всеми его значениями. Например, замените

else if (node.isValueNode()) {
...
}

на

else if (node.isValueNode()) {
    ValueNode valueNode = (ValueNode) node;
    final List<String> values = map.getOrDefault(currentpath, new ArrayList<>());
    values.add(valueNode.asText());
    map.put(currentpath, values);
}

Если вы сейчас введете идентификатор, он покажет все значения в списке.

...