NullPointerException:使用GSON在JAVA中进行JSON解析

7 java json nullpointerexception gson

我想使用Api GSON通过java解析JSON文件以获取JSON文件的最后一个字段:

descriptor.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"]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

TeleService.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Record.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我的解析器类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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎是正确的,它应该显示:"amine1",但它给我一个nullPointerException:

ListTeleServices.getTeleService(ListTeleServices.java:12),它是:

if(this.listTeleServices.get(teleserviceName) != null) 
Run Code Online (Sandbox Code Playgroud)

在JSONMainParse.main(JSONMainParse.java:15)它是:

String methodName = teleservices.getTeleService("Teleservice_2").getRecord("Record_33").getMethodName();
Run Code Online (Sandbox Code Playgroud)

你对此有什么想法吗?谢谢 :)

Mik*_*ikO 8

解:

您正在使用比解析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);
Run Code Online (Sandbox Code Playgroud)

最后,为了获取方法名称,您必须使用:

String methodName = map.get("Teleservice_2").get("Record_33").getMethodName();
Run Code Online (Sandbox Code Playgroud)

说明:

当您使用类ListTeleServices在此处解析JSON时:

ListTeleServices teleservices = gson.fromJson(br, ListTeleServices.class);
Run Code Online (Sandbox Code Playgroud)

Gson做的是分析类ListTeleServices并将其与JSON响应进行比较,因此它说:

  1. 你传递了一个类ListTeleServices.class,JSON响应以一个对象开始{}......到目前为止一切正常!

  2. 然后它继续解析JSON,并且:

    • 在类中,ListTeleServices它找到一个属性listTeleServices,它是某个对象(暂时不介意类型).
    • 然而,在JSON响应它找到三个要素"Teleservice_1","Teleservice_2"并且"Teleservice_3",但是他们都没有相同的名称listTeleServices,所以GSON跳过所有这些值,并分配null到属性listTeleServices...

请记住,Gson需要JSON响应中的名称与您用于解析响应的类中的名称相同.

另一方面,如果直接使用a Map<String, Map<String, Record>>,Gson会看到:

  1. 你传递了类型Map<String, Map<String, Record>>,JSON响应以一个对象开始{}......到目前为止一切正常!(记住一个Map只是一个对象)

  2. 然后它继续解析JSON,并且:

    • Map<String, Map<String, Record>>它看到必须有一些键(字符串)和值(一些对象).
    • 而在JSON响应发现正是这样,一些字符串对"Teleservice_1","Teleservice_2""Teleservice_3"和一些对象{},因此它可以保持愉快解析...

PS:要进一步说明,请注意您可以在班级中拥有ListTeleServices以下属性:

private HashMap<String, Record> Teleservice_1;
private HashMap<String, Record> Teleservice_2;
private HashMap<String, Record> Teleservice_3;
Run Code Online (Sandbox Code Playgroud)

它会很好用,但这样你就不能拥有任意数量的远程服务对象......


顺便说一句,我也意识到了其他错误:在你的Response类中,属性名称method_parameters与JSON响应中的字段名称不匹配,即method_params.您可以更改属性名称或使用注释:

@SerializedName("method_params")
private Object[] method_parameters;
Run Code Online (Sandbox Code Playgroud)