NullPointerException: синтаксический анализ JSON в JAVA с использованием GSON

Я хочу проанализировать файл JSON через java с помощью Api GSON, чтобы получить последние поля файла JSON:

дескриптор.в JSON :

{
    "Teleservice_1" : {
        "Record_1" : {
            "method_name" : "mehdi",
            "method_params": ["param1",2,"param3"]
        },
        "Record_2" : {
            "method_name" : "mkyong",
            "method_params": [3,"param2"]
        },
        "Record_3" : {
            "method_name" : "amine",
            "method_params": [3,"param1","param2"]
        }
    },
    "Teleservice_2" : {
        "Record_11" : {
            "method_name" : "mehdi1",
            "method_params": ["param11",22,"param33"]
        },
        "Record_22" : {
            "method_name" : "mkyong1",
            "method_params": [33,"param22"]
        },
        "Record_33" : {
            "method_name" : "amine1",
            "method_params": [33,"param11","param22"]
        }
    },
    "Teleservice_3" : {
        "Record_111" : {
            "method_name" : "mehdi2",
            "method_params": ["param111",222,"param333"]
        },
        "Record_222" : {
            "method_name" : "mkyong2",
            "method_params": [333,"param222"]
        },
        "Record_333" : {
            "method_name" : "amine2",
            "method_params": [333,"param111","param222"]
        }
    }
}

ListTeleServices.java:

import java.util.HashMap;

public class ListTeleServices {

    private HashMap<String, TeleService> listTeleServices;

    public ListTeleServices() {

    }

    public TeleService getTeleService(String teleserviceName) {
        if(this.listTeleServices.get(teleserviceName) != null) 
            return this.listTeleServices.get(teleserviceName);
        else
            return null;
    }
}

Телесервиса.java:

import java.util.HashMap;

public class TeleService {

    private HashMap<String, Record> listRecords;

    public TeleService() {

    }

    public Record getRecord(String recordName) {
        if(this.listRecords.get(recordName) != null) 
            return this.listRecords.get(recordName);
        else
            return null;
    }
}

запись.java:

public class Record {

    private String method_name;
    private Object[] method_parameters; 

    public Record(String methodName, Object[] methodParameters) {
        this.method_name = new String(methodName);
        this.method_parameters = methodParameters;
    }

    public String getMethodName() {
        return this.method_name;
    }

    public Object[] getMethodParameters() {
        return this.method_parameters;
    }

    public void setMethodName(String methodName) {
        this.method_name = methodName;
    }

    public void setMethodParameters(Object[] methodParameters) {
        this.method_parameters = methodParameters;
    }
}

и, наконец, мой класс парсера,JSONMainParse.java:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import com.google.gson.Gson;


public class JSONMainParse {

    public static void main(String[] args) throws FileNotFoundException {

        BufferedReader br = new BufferedReader(new FileReader("/Users/Mehdi/Desktop/descriptor.json"));
        Gson gson = new Gson();
        ListTeleServices teleservices = gson.fromJson(br, ListTeleServices.class);
        String methodName = teleservices.getTeleService("Teleservice_2").getRecord("Record_33").getMethodName();

        System.out.println(methodName);
    }
}

кажется правильно для меня, и он должен отображать: "amine1", но это дает мне nullPointerException at:

ListTeleServices.getTeleService (ListTeleServices.java: 12) что :

if(this.listTeleServices.get(teleserviceName) != null) 

и в JSONMainParse.main (JSONMainParse.java: 15) что :

String methodName = teleservices.getTeleService("Teleservice_2").getRecord("Record_33").getMethodName();

у вас есть какие-либо идеи по этому поводу ? Спасибо :)

3 ответов


устранение:

вы используете больше классов, чем необходимо для анализа ответа JSON! Вы можете удалить свои классы ListTeleServices и TeleService и оставить только Record класса.

Gson gson = new Gson();
Type mapOfMapsType = new TypeToken<Map<String, Map<String, Record>>>() {}.getType();
Map<String, Map<String, Record>> map = gson.fromJson(br, mapOfMapsType);

наконец, чтобы получить имя метода, вы должны использовать:

String methodName = map.get("Teleservice_2").get("Record_33").getMethodName();

объяснение:

когда вы используете ваш класс ListTeleServices чтобы разобрать JSON здесь:

ListTeleServices teleservices = gson.fromJson(br, ListTeleServices.class);

что Дсын это эналайз класс ListTeleServices и сравните его с ответом JSON, поэтому он говорит:

  1. вы прошли класс ListTeleServices.class, и ответ JSON начинается с объекта {}... пока все в порядке!

  2. затем он продолжает анализировать JSON и:

    • в классе ListTeleServices находит атрибут listTeleServices что какой-то объект (не вида на данный момент).
    • однако в ответе JSON он находит три элемента "Teleservice_1", "Teleservice_2" и "Teleservice_3", но ни один из них не имеет того же имени listTeleServices, поэтому Gson пропускает все эти значения и присваивает null атрибут listTeleServices...

помните, что Gson нуждается в именах в ответе JSON, чтобы быть тем же, что и в классе, который вы используете для анализа ответа.

С другой стороны, если вы используете непосредственно Map<String, Map<String, Record>>, Дсын см.:

  1. вы прошли типа Map<String, Map<String, Record>>, и ответ JSON начинается с объекта {}... пока все в порядке! (Помню Map - это просто объект)

  2. затем он продолжает анализировать JSON и:

    • на Map<String, Map<String, Record>> он видит, что должны быть некоторые пары ключа (строка) и значения (некоторый объект).
    • и в ответе JSON он находит именно это, некоторые пары строк "Teleservice_1", "Teleservice_2" и "Teleservice_3", и некоторые объекты {}, поэтому он может продолжать разбор счастливо...

П. С.: чтобы пойти дальше, обратите внимание, что вы могли бы иметь в своем классе ListTeleServices этих атрибутов:

private HashMap<String, Record> Teleservice_1;
private HashMap<String, Record> Teleservice_2;
private HashMap<String, Record> Teleservice_3;

и это будет работать хорошо, но таким образом вы не можете иметь произвольное количество объектов Телесервиса...


и кстати, я понял другая ошибка: в Response класс, имя атрибута method_parameters не соответствует имени Поля в ответе JSON, которая составляет method_params. Вы можете изменить имя атрибута или использовать аннотации:

@SerializedName("method_params")
private Object[] method_parameters;

инициализации

private HashMap<String, TeleService> listTeleServices;

as

private HashMap<String, TeleService> listTeleServices = new HashMap<>();

в текущем коде вы пытаетесь вызвать get() на null ссылка на объект, который бросает NullPointerException , а ты попытка вызвать метод экземпляра для нулевого объекта.


изменить это:

private HashMap<String, TeleService> listTeleServices;

этой

private HashMap<String, TeleService> listTeleServices = new HashMap<String,TeleService>();