Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Gson解析JSON(流模式)时发生JAVA错误:应为BEGIN_数组,但在第1行第2列路径处为BEGIN_对象$_Java_Json_Gson - Fatal编程技术网

使用Gson解析JSON(流模式)时发生JAVA错误:应为BEGIN_数组,但在第1行第2列路径处为BEGIN_对象$

使用Gson解析JSON(流模式)时发生JAVA错误:应为BEGIN_数组,但在第1行第2列路径处为BEGIN_对象$,java,json,gson,Java,Json,Gson,更新:我已经根据第一次回复中的建议修改了代码,但仍然产生了一个错误。 我编写了以下代码来解析一个非常大的json文件: public static void main(String[] args) throws Exception { String jsonFile="/home/zz/Work/data/wdc/WDC_ProdMatch/idclusters.json"; WDCProdMatchDatasetIndexer_2 indexer = n

更新:我已经根据第一次回复中的建议修改了代码,但仍然产生了一个错误。

我编写了以下代码来解析一个非常大的json文件:

    public static void main(String[] args) throws Exception {
        String jsonFile="/home/zz/Work/data/wdc/WDC_ProdMatch/idclusters.json";
        WDCProdMatchDatasetIndexer_2 indexer = new WDCProdMatchDatasetIndexer_2();
        indexer.readClusterMetadata(jsonFile);
    }

    public void readClusterMetadata(String jsonFile){
        try(JsonReader jsonReader = new JsonReader(
                new InputStreamReader(
                        new FileInputStream(jsonFile), StandardCharsets.UTF_8))) {

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

            jsonReader.beginObject(); //start of json array
            int numberOfRecords = 0;
            while (jsonReader.hasNext()){ //next json array element
                Cluster c = gson.fromJson(jsonReader, Cluster.class);
                long[] sizeInfo=new long[]{c.clusterSizeInOffers, c.size};
                //clusterSize.put(String.valueOf(c.id), sizeInfo);

                numberOfRecords++;
                if (numberOfRecords%1000==0)
                    System.out.println(String.format("processed %d clusters", numberOfRecords));
            }
            jsonReader.endArray();
            System.out.println("Total Records Found : "+numberOfRecords);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }


    class ArrayAsStringJsonDeserializer implements JsonDeserializer<List<String>> {
        @Override
        public List<String> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            String value = json.getAsString().trim();
            value = value.substring(1, value.length() - 1);

            return Arrays.stream(value.split(",")).map(String::trim).collect(Collectors.toList());
        }
    }


    class Cluster {
        protected long id;
        protected long size;

        @SerializedName("cluster_size_in_offers")
        protected long clusterSizeInOffers;

        @JsonAdapter(ArrayAsStringJsonDeserializer.class)
        @SerializedName("id_values")
        protected List<String> idValues;

        @SerializedName("categoryDensity")
        protected double catDensity;

        @SerializedName("category")
        protected String cat;
    }
但是,当代码在此数据上运行时,会生成如下错误:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NAME at line 1 column 3 path $.
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
    at com.google.gson.Gson.fromJson(Gson.java:927)
    at uk.ac.shef.inf.wop.indexing.WDCProdMatchDatasetIndexer_2.readClusterMetadata(WDCProdMatchDatasetIndexer_2.java:38)
    at uk.ac.shef.inf.wop.indexing.WDCProdMatchDatasetIndexer_2.main(WDCProdMatchDatasetIndexer_2.java:25)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NAME at line 1 column 3 path $.
    at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215)
    ... 3 more

有什么建议吗?

在一个文件中,每一行都是一个单独的
JSON对象。它的一个问题是
JSON数组
用引号括起来,这使得它成为
字符串
原语。您需要为它提供自定义反序列化程序,从引号中展开数组,并通过逗号手动拆分项目(
)。示例解决方案如下所示:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.ToString;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        List<Cluster> clusters = readClusters(jsonFile);
        clusters.forEach(System.out::println);
    }

    private static List<Cluster> readClusters(File jsonFile) throws IOException {
        Gson gson = new GsonBuilder().create();

        try (Stream<String> lines = Files.lines(jsonFile.toPath())) {
            return lines
                    .map(line -> gson.fromJson(line, Cluster.class))
                    .collect(Collectors.toList());
        }
    }
}

class ArrayAsStringJsonDeserializer implements JsonDeserializer<List<String>> {
    @Override
    public List<String> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        String value = json.getAsString().trim();
        value = value.substring(1, value.length() - 1);

        return Arrays.stream(value.split(",")).map(String::trim).collect(Collectors.toList());
    }
}

@Data
@ToString
class Cluster {
    protected long id;
    protected long size;

    @SerializedName("cluster_size_in_offers")
    protected long clusterSizeInOffers;

    @JsonAdapter(ArrayAsStringJsonDeserializer.class)
    @SerializedName("id_values")
    protected List<String> idValues;

    @SerializedName("categoryDensity")
    protected int catDensity;

    @SerializedName("category")
    protected String cat;
}

文件的每一行都是一个对象,因此您确实需要使用beginObject,而不是beginArray。。。这会导致什么错误?谢谢你的快速回复,我刚刚更新了信息。POST末尾的错误消息建议逐行读取文件,然后像Gson中的正常情况一样反序列化整个字符串。然后,您可以避免流逻辑(需要在循环内而不是在循环外打开和关闭对象),您的代码希望json以数组开头。但如果您看到json,它就是一个对象。这就是为什么会有例外谢谢你的板球。。。我想我需要与数据提供者核实,他们确实已逐行分离数据记录;比拉尔,我也试着把A行改成“beginObject”,但这会产生一个不同的错误,正如文章末尾所说的。非常感谢您花时间阅读我的代码。我已经根据您的修改了我的代码,因为我的数据量很大(9GB),我需要处理流中的数据。我改编的代码现在反映在原来的帖子中。但是我仍然得到一个上面描述的错误…@Ziqi,您不能将
jsonReader
提供给
Gson
,因为它将一直读取到文件末尾,并且崩溃,因为您在每一行中都有新的
JSON
对象。您应该删除所有行,如
jsonReader.beginObject()
。你不能这样解析它。如果只想读取前1000行,还可以通过在
收集
之前添加
.limit(1000)
来限制
。或者,如果您不想收集所有数据并保存它们,您可以调用
forEach
方法。那么,您的代码一次读取一行并将其解析为一个对象,对吗?也就是说,它不再使用JsonReader来处理流(Files.lines…)。如果是这样的话,我想我可以知道如何适应它。。。thanks@Ziqi,没错
Files.lines(jsonFile.toPath())
line返回
Stream
对象,该对象逐行惰性地读取文件。因此,例如,如果您想处理所有行并将它们保存到DB,您可以向流中的链添加
forEach
调用,并将给定的
POJO
保存到DB。更改我的代码应该很容易
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.ToString;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        List<Cluster> clusters = readClusters(jsonFile);
        clusters.forEach(System.out::println);
    }

    private static List<Cluster> readClusters(File jsonFile) throws IOException {
        Gson gson = new GsonBuilder().create();

        try (Stream<String> lines = Files.lines(jsonFile.toPath())) {
            return lines
                    .map(line -> gson.fromJson(line, Cluster.class))
                    .collect(Collectors.toList());
        }
    }
}

class ArrayAsStringJsonDeserializer implements JsonDeserializer<List<String>> {
    @Override
    public List<String> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        String value = json.getAsString().trim();
        value = value.substring(1, value.length() - 1);

        return Arrays.stream(value.split(",")).map(String::trim).collect(Collectors.toList());
    }
}

@Data
@ToString
class Cluster {
    protected long id;
    protected long size;

    @SerializedName("cluster_size_in_offers")
    protected long clusterSizeInOffers;

    @JsonAdapter(ArrayAsStringJsonDeserializer.class)
    @SerializedName("id_values")
    protected List<String> idValues;

    @SerializedName("categoryDensity")
    protected int catDensity;

    @SerializedName("category")
    protected String cat;
}
Cluster(id=2, size=4, clusterSizeInOffers=1, idValues=[814914023129, w2190254, pfl60gs25ssdr, pfl60gs25ssdr], catDensity=1, cat=Computers_and_Accessories)
Cluster(id=3, size=2, clusterSizeInOffers=1, idValues=[hst322440ss, g1042641], catDensity=1, cat=Office_Products)
Cluster(id=4, size=4, clusterSizeInOffers=1, idValues=[4051329063869, t24datr01765, t24datr01763, datr01763], catDensity=1, cat=Automotive)
...