有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java 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_对象,但在第1行第3401列是BEGIN_数组”(第3401列是第一个[]的确切位置)


共 (3) 个答案

  1. # 1 楼答案

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

    "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("\\[]", "");
    

    我希望这有帮助

  2. # 3 楼答案

    您总是可以使用类型适配器来适应设计糟糕但格式良好的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 -> {
                    });
        }
    }
    

    输出:

    Prize: 1902 physics
    ........Affiliation: Leiden University Leiden the Netherlands
    Prize: 1903 physics