当它需要一个对象时,gson会出现空数组的问题

时间:2018-04-02 00:10:15

标签: java json gson

我试图使用gson处理json文件,但我遇到了一个奇怪的错误。我从中读取的json(并且不能修改)有一种处理空字段的奇怪方法。它将[]置于没有数据的地方,导致gson认为它是一个数组,当它期待一个对象时。

gson的一个例子:

//non-empty field
"prizes":[
            {
                "year":"1902",
                "category":"physics",
                "share":"2",
                "motivation":"\"in recognition of the extraordinary service they rendered by their researches into the influence of magnetism upon radiation phenomena\"",
                "affiliations":[
                    {
                        "name":"Leiden University",
                        "city":"Leiden",
                        "country":"the Netherlands"
                    }
                ]
            }
        ]

//empty field
"prizes":[
            {
                "year":"1903",
                "category":"physics",
                "share":"4",
                "motivation":"\"in recognition of the extraordinary services they have rendered by their joint researches on the radiation phenomena discovered by Professor Henri Becquerel\"",
                "affiliations":[
                    []
                ]
            }
        ]

这是我处理json的代码:

public static void main(String[] args) throws IOException {
    // Get Gson object
    Gson gson = new Gson();

    // read JSON file data as String
    String fileData = new 
    String(Files.readAllBytes(Paths.get("laureates.json")));

    // parse json string to object
    Example laur = gson.fromJson(fileData, Example.class);

    // print object data
    System.out.println("\n\nLaureates Object\n\n" + laur);
}

我已经设置了所有课程,我相信一旦这个问题得到解决,它就会起作用。 我得到的错误是"预期BEGIN_OBJECT但是在第1行第3401行"是BEGIN_ARRAY。 (第3401列是第一个[])

的确切位置

3 个答案:

答案 0 :(得分:0)

设置空对象的正确方法是没有括号。你知道的。 : - )

"prizes":[
        {
            "year":"1903",
            "category":"physics",
            "share":"4",
            "motivation":"\"in recognition of the extraordinary services they have rendered by their joint researches on the radiation phenomena discovered by Professor Henri Becquerel\"",
            "affiliations":[
            ]
        }
    ]

您可以删除括号。

fileData = fileData.replaceAll("\\[]", "");

我希望这会有所帮助。

答案 1 :(得分:0)

看起来gson期待一个对象但是返回了数组  尝试将Example更改为数组,如下所示。

Example[] emps= gson.fromJson(yourJson, Example
[].class);

另请参阅相关的GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"?

答案 2 :(得分:0)

您始终可以使用类型适配器来调整设计错误但格式正确的JSON文档。例如,以下类型适配器可以修复您的情况:

final class EmptyListFixTypeAdapterFactory
        implements TypeAdapterFactory {

    private static final TypeAdapterFactory instance = new EmptyListFixTypeAdapterFactory();

    private EmptyListFixTypeAdapterFactory() {
    }

    static TypeAdapterFactory get() {
        return instance;
    }

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        // If it's not a list, then just let Gson pass through the rest of the type adapters chain
        if ( !List.class.isAssignableFrom(typeToken.getRawType()) ) {
            return null;
        }
        // Get the original List adapter - we'll use it below
        @SuppressWarnings("unchecked")
        final TypeAdapter<List<Object>> delegateTypeAdapter = (TypeAdapter<List<Object>>) gson.getDelegateAdapter(this, typeToken);
        // Wrap it
        @SuppressWarnings("unchecked")
        final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) EmptyListFixTypeAdapter.get(delegateTypeAdapter);
        return typeAdapter;
    }

    private static final class EmptyListFixTypeAdapter<E>
            extends TypeAdapter<List<E>> {

        // JsonParser as of Gson 2.8.2 holds no state
        private static final JsonParser jsonParser = new JsonParser();

        private final TypeAdapter<List<E>> delegateTypeAdapter;

        private EmptyListFixTypeAdapter(final TypeAdapter<List<E>> delegateTypeAdapter) {
            this.delegateTypeAdapter = delegateTypeAdapter;
        }

        private static <E> TypeAdapter<List<E>> get(final TypeAdapter<List<E>> delegateTypeAdapter) {
            return new EmptyListFixTypeAdapter<>(delegateTypeAdapter)
                    .nullSafe(); // A convenient method to add null-checking automatically
        }

        @Override
        public void write(final JsonWriter out, final List<E> value)
                throws IOException {
            // In case if you need to produce document with this quirks
            if ( value.isEmpty() ) {
                out.beginArray();
                out.beginArray();
                out.endArray();
                out.endArray();
                return;
            }
            delegateTypeAdapter.write(out, value);
        }

        @Override
        public List<E> read(final JsonReader in) {
            final JsonElement jsonElement = jsonParser.parse(in);
            final JsonArray array = jsonElement.getAsJsonArray();
            // Is it [[]]?
            if ( array.size() == 1 ) {
                final JsonElement element = array.get(0);
                if ( element.isJsonArray() && ((JsonArray) element).size() == 0 ) {
                    // Yes, detected
                    return new ArrayList<>();
                }
            }
            // No, proceed with the delegate type adapter
            return delegateTypeAdapter.fromJsonTree(array);
        }

    }

}

现在假设您有以下映射:

final class Laureate {
    final List<Prize> prizes = new ArrayList<>();
}

final class Prize {
    final int year = Integer.valueOf(0);
    final String category = null;
    final List<Affiliation> affiliations = new ArrayList<>();
}

final class Affiliation {
    final String name = null;
    final String city = null;
    final String country = null;
}

然后:

private static final Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(EmptyListFixTypeAdapterFactory.get())
        .create();

private static final Type laureatesType = new TypeToken<List<Laureate>>() {
}.getType();

public static void main(final String... args)
        throws IOException {
    try ( final JsonReader jsonReader = Resources.getPackageResourceJsonReader(Q49603826.class, "laureates.json") ) {
        gson.<List<Laureate>>fromJson(jsonReader, laureatesType)
                .stream()
                .flatMap(laureate -> laureate.prizes.stream())
                .peek(prize -> System.out.println("Prize: " + prize.year + " " + prize.category))
                .flatMap(prize -> prize.affiliations.stream())
                .peek(affiliation -> System.out.println("\tAffiliation: " + affiliation.name + " " + affiliation.city + " " + affiliation.country))
                .forEach(affiliation -> {
                });
    }
}

输出:

  

奖项:1902年物理学   ........隶属:莱顿大学莱顿荷兰
  奖项:1903年物理学