gson反序列化没有标识符的对象数组

时间:2017-03-08 11:38:41

标签: java gson

我在尝试将json数组带到对象列表时遇到错误,例外情况如下。

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 170

这是我正在尝试使用的代码

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

    Gson gson = new Gson();

    Test test = new Test();

    JsonElement json = gson.fromJson(test.getFile("fieldTypes.json"), JsonElement.class);
    String result = gson.toJson(json);

    System.out.println(result);

    Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();

    JiraField[]  jiraFields = gson.fromJson(result, listType);

    for (JiraField jiraField : jiraFields) {
        System.out.println(jiraField);
    }
}

这是文件内容

[
{
"id": "issuetype",
"key": "issuetype",
"name": "Issue Type",
"custom": false,
"orderable": true,
"navigable": true,
"searchable": true,
"clauseNames": [
  "issuetype",
  "type"
],
"schema": {
  "type": "issuetype",
  "system": "issuetype"
}
},
{
"id": "timespent",
"key": "timespent",
"name": "Time Spent",
"custom": false,
"orderable": false,
"navigable": true,
"searchable": false,
"clauseNames": [
  "timespent"
],
"schema": {
  "type": "number",
  "system": "timespent"
}
}
]

正在从资源文件夹中读取文件但是工作正常,并且sysout正确显示了json内容。我认为我做错了什么?

5 个答案:

答案 0 :(得分:0)

好的,所以。原来是由未映射的字段引起的,这就是我如何工作

在对象中为所需字段添加@Expose注释

public class JiraField {

@Expose
private String id ;
@Expose private String key ;
@Expose private String name ;
@Expose private boolean custom ;
@Expose private boolean orderable ;
@Expose private boolean navigable ;
@Expose private String[] clauseNames ;

然后当你初始化gson时,就像这样做

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

然后它起作用:)

JiraFields{id='issuetype', key='issuetype', name='Issue Type', custom=false, orderable=true, navigable=true, clauseNames=[issuetype, type]}
JiraFields{id='timespent', key='timespent', name='Time Spent', custom=false, orderable=false, navigable=true, clauseNames=[timespent]}

答案 1 :(得分:0)

试试这个:

    Type listType = new TypeToken<ArrayList<JiraField[]>>(){}.getType();

我认为我们需要按顺序指定JiraField []以获取Array。

答案 2 :(得分:0)

我假设您根据异常消息...at line 1 column 170...拥有缩小的JSON。如果您提供完全正确的JSON文档和映射也会很好,因为发布的格式化JSON现在已经破坏了布局。我还假设您的映射是自定义的,基本上类似于:

final class JiraField {

    @SerializedName("id")
    final String id = null;

    @SerializedName("key")
    final String key = null;

    @SerializedName("name")
    final String name = null;

    @SerializedName("custom")
    final boolean isCustom = Boolean.valueOf(false);

    @SerializedName("orderable")
    final boolean isOrderable = Boolean.valueOf(false);

    @SerializedName("navigable")
    final boolean isNavigable = Boolean.valueOf(false);

    @SerializedName("searchable")
    final boolean isSearchable = Boolean.valueOf(false);

    @SerializedName("clauseNames")
    final List<String> clauseNames = null;

    @SerializedName("schema")
    final List<String> schema = null;

}

请注意JiraField.schema字段类型:它是一个列表。尝试使用默认的Gson配置反序列化JiraField列表将导致:

  

java.lang.IllegalStateException:预期为BEGIN_ARRAY,但在第1行第170行路径为$ [0] .schema

时为BEGIN_OBJECT

症状和列完全相同(但是,我只是简化你的JSON文件的缩小),但请注意你可能错过的路径$[0].schema:它说的是数组开始标记[是预期的(因为该字段是List<String>),但它是一个对象开始标记{。将字段类型更改为更合适的任意Map<String, String>或任何其他自定义的适当POJO将修复它。部分。

@SerializedName("schema")
final Map<String, String> schema = null;

为何部分?您的类型令牌已绑定到ArrayList,但您将反序列化结果转换为数组JiraField[],因此您可以获得以下内容:

  

线程中的异常&#34; main&#34; java.lang.ClassCastException:java.util.ArrayList无法强制转换为[LJiraField;

要修复它,你必须声明与反序列化值类型匹配的jiraFields变量:它是一个数组列表,但不是数组 - 这些在Java中是不一样的。

List<JiraField> jiraFields = ...

关于反序列化的另一个注意事项是,您不需要中间json对象来反序列化。 test.getFile最有可能返回java.io.Reader,因此您可以直接将其传递给反序列化。总结一下,以下内容适合您:

// Immutable and thread-safe, can be instantiated once and shared
private static final Gson gson = new Gson();

// Immutable and thread-safe value type, the same story, + List instead of ArrayList - interfaces are usually much better
private static final Type listType = new TypeToken<List<JiraField>>() {
}.getType();

public static void main(final String... args)
        throws IOException {
    try ( final Reader reader = test.getFile("fieldTypes.json") ) {
        final List<JiraField> jiraFields = gson.fromJson(reader, listType);
        for ( final JiraField jiraField : jiraFields ) {
            System.out.println(jiraField.key + " => " + jiraField.name);
        }
    }
}

输出:

  

issuetype =&gt;问题类型
  timespent =&gt;花费的时间

答案 3 :(得分:0)

Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();

ArrayList<JiraField>  jiraFields = gson.fromJson(result, listType);

for (JiraField jiraField : jiraFields) {
    System.out.println(jiraField);
}

尝试此代码

答案 4 :(得分:0)

评论此行

Type listType = new TypeToken<ArrayList<JiraField>>(){}.getType();

试试这个

JiraField[]  jiraFields = gson.fromJson(result, JiraField[].class);