Как обработать элемент json после разбора с помощью библиотеки GSON? - PullRequest
0 голосов
/ 07 марта 2019

Я установил следующую полезную нагрузку в Gson JsonObject:

 {
        "backup": {
            "addresses": [
                "127.0.0.1"
            ], 
            "healthcheck_interval": "60", 
            "http": "https", 
            "port": "9001"
        }, 
        "cognito": {
            "addresses": [
                "127.0.0.1"
            ], 
            "http": "https", 
            "port": "9012"
        }, 
        "collector": {
            "addresses": [
                "127.0.0.1"
            ], 
            "healthcheck_interval": "60", 
            "http": "https", 
            "port": "9000"
        }, 
        "ds": {
            "addresses": [
                "127.0.0.1"
            ], 
            "http": "https", 
            "port": "9011"
        }, 
        "insight-analytics": {
            "addresses": [
                "127.0.0.1"
            ], 
            "http": "https", 
            "port": "9013"
        }, 
        "integrations": {
            "addresses": [
                "127.0.0.1"
            ], 
            "http": "https", 
            "port": "9014"
        }, 
        "server": {
            "addresses": [
                "127.0.0.1"
            ], 
            "healthcheck_interval": "60", 
            "http": "https", 
            "port": "9009"
        }, 
        "vigile": {
            "addresses": [
                "127.0.0.1"
            ], 
            "http": "https", 
            "port": "9443"
        }, 
        "walt": {
            "addresses": [
                "127.0.0.1"
            ], 
            "http": "https", 
            "port": "9010"
        }
    }

Тест:

@Test(priority = 10)
public void parseServicesFileToGsonObject() {
 JsonParser jsonParser = new JsonParser();
 JsonElement rootNode = jsonParser.parse(response);
 if (rootNode.isJsonObject()) {
  JsonObject details = rootNode.getAsJsonObject();
 }
}

Я хочу иметь возможность хранить все члены JSON в строковом массиве (backup, cognito, collector и т. Д.) Таким образом, чтобы я мог найти объект, используя строковый массив для получить дополнительные значения (например, healthcheck_interval, http, port и т. д.). Я попытался использовать потоки по этой причине, но безуспешно. Я хочу сделать это, поскольку вполне возможно, что в будущем имена полей могут быть изменены (вместо backup оно может быть изменено на другое имя).

Ответы [ 2 ]

1 голос
/ 07 марта 2019

Самый общий способ - использовать Map<String, Object> для представления динамической структуры полезной нагрузки JSON. В этом случае мы всегда можем использовать метод Map#keySet(), чтобы перечислить все свойства, и нам не нужно никаких String[] для их сохранения. Кроме того, поиск объектов по ключу быстрее, чем использование array или List. Если значения нашего объекта имеют постоянную структуру, мы можем сопоставить его с POJO, чтобы иметь стабильный доступ к значениям во время выполнения. Ниже код показывает оба случая:

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

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.List;
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();

        System.out.println("Use generic Map");
        Type genericMapType = new TypeToken<Map<String, Object>>() {
        }.getType();
        Map<String, Object> map = gson.fromJson(new FileReader(jsonFile), genericMapType);
        map.forEach((k, v) -> System.out.println(k + " => " + v));

        System.out.println();
        System.out.println();

        System.out.println("Use Service Map");
        Type serviceMapType = new TypeToken<Map<String, Service>>() {
        }.getType();
        Map<String, Service> serviceMap = gson.fromJson(new FileReader(jsonFile), serviceMapType);
        serviceMap.forEach((k, v) -> System.out.println(k + " => " + v));
    }
}

class Service {
    private List<String> addresses;

    @SerializedName("healthcheck_interval")
    private int healthCheckInterval;
    private String http;
    private int port;

    public List<String> getAddresses() {
        return addresses;
    }

    public void setAddresses(List<String> addresses) {
        this.addresses = addresses;
    }

    public int getHealthCheckInterval() {
        return healthCheckInterval;
    }

    public void setHealthCheckInterval(int healthCheckInterval) {
        this.healthCheckInterval = healthCheckInterval;
    }

    public String getHttp() {
        return http;
    }

    public void setHttp(String http) {
        this.http = http;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    @Override
    public String toString() {
        return "Service{" +
                "addresses=" + addresses +
                ", healthCheckInterval=" + healthCheckInterval +
                ", http='" + http + '\'' +
                ", port=" + port +
                '}';
    }
}

Над отпечатками кода:

Use generic Map
backup => {addresses=[127.0.0.1], healthcheck_interval=60, http=https, port=9001}
cognito => {addresses=[127.0.0.1], http=https, port=9012}
collector => {addresses=[127.0.0.1], healthcheck_interval=60, http=https, port=9000}
ds => {addresses=[127.0.0.1], http=https, port=9011}
insight-analytics => {addresses=[127.0.0.1], http=https, port=9013}
integrations => {addresses=[127.0.0.1], http=https, port=9014}
server => {addresses=[127.0.0.1], healthcheck_interval=60, http=https, port=9009}
vigile => {addresses=[127.0.0.1], http=https, port=9443}
walt => {addresses=[127.0.0.1], http=https, port=9010}


Use Service Map
backup => Service{addresses=[127.0.0.1], healthCheckInterval=60, http='https', port=9001}
cognito => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9012}
collector => Service{addresses=[127.0.0.1], healthCheckInterval=60, http='https', port=9000}
ds => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9011}
insight-analytics => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9013}
integrations => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9014}
server => Service{addresses=[127.0.0.1], healthCheckInterval=60, http='https', port=9009}
vigile => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9443}
walt => Service{addresses=[127.0.0.1], healthCheckInterval=0, http='https', port=9010}
1 голос
/ 07 марта 2019

Вам нужно переосмыслить свою проблему.Хорошая вещь о GSON заключается в том, что он способен рефлексивно сериализовать и десериализовать JSON из реальных объектов Java.

Это означает, что вы должны сначала определить свой объект, а затем позволить GSON выполнить грязную работу, например:

class Server
{
  List<String> addresses;
  int healthcheck_interval;
  String http;
  int port;
}

, чтобы вы могли иметь

GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();

List<Server> servers = gson.fromJson(json, 
  new TypeToken<List<Server>>(){}.getType()
);
...