Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.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
Java GSON:JSON反序列化为变量类型(列表/字符串)_Java_Json_Gson_Deserialization_Retrofit - Fatal编程技术网

Java GSON:JSON反序列化为变量类型(列表/字符串)

Java GSON:JSON反序列化为变量类型(列表/字符串),java,json,gson,deserialization,retrofit,Java,Json,Gson,Deserialization,Retrofit,在这一点上,这已经是一个老问题,我可能已经阅读了所有相关的主题 但切中要害。我可能需要一些建议或更正 出于某种原因,我们有两种类型的可生成JSON: {“数据”:{“id”:“value”}和{“data”:[{“id”:“value”}]} 对象和数组。还有其他参数,但它们在这里并不重要。每个请求的“id”都不同。有时是userId、portfolioId等,所以我获取“id”并将其传递给相关的var 很长一段时间我都在处理第一个案子。并创建了如下POJO: 数据类 public class

在这一点上,这已经是一个老问题,我可能已经阅读了所有相关的主题

但切中要害。我可能需要一些建议或更正

出于某种原因,我们有两种类型的可生成JSON:

{“数据”:{“id”:“value”}
{“data”:[{“id”:“value”}]}

对象和数组。还有其他参数,但它们在这里并不重要。每个请求的“id”都不同。有时是userId、portfolioId等,所以我获取“id”并将其传递给相关的var

很长一段时间我都在处理第一个案子。并创建了如下POJO:

数据类

public class Data {

@SerializedName("id")
@Expose
private String id;

public Data() {
}

public Data(String id) {
    super();
    this.id = id;
}

protected String getId() {
    return id;
}
 public class UserDeserializer implements JsonDeserializer<User> {

    private Type listType = new TypeToken<List<Data>>(){}.getType();

    @Override
    public User deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {

        User user = new User();
        JsonElement jsonElement;
        if (json.isJsonArray()) {
            jsonElement = json.getAsJsonArray();
            user.data = context.deserialize(jsonElement,listType);
//            user.data = new Gson().fromJson(jsonElement, new TypeToken<List<Data>>() {}.getType());
        } else {
            jsonElement = json.getAsJsonObject();
            user.data = context.deserialize(jsonElement, Data.class);
//            user.setData(new Gson().fromJson(jsonElement, new TypeToken<Data>() {}.getType()));
        }
        return user;
    }
}
我通过User.class处理“数据”参数

@JsonAdapter(UserDeserializer.class)
public Data data;


public Data getData() {
    return data;
}

public void setData(Data data) {
    this.data = data;
}


public User() {
}

public User(Data data) {
    super();
    this.data = data;
}

Gson gson = new Gson();

public String getPortfolioList(String tokenId, String userId) {
    Call<User> call = apiRequest.getPortfolioList(userId, tokenId);

    try {
        User newResult = gson.fromJson(String.valueOf(call.execute().body()), User.class);
        System.out.println(newResult.getData().getId());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return getPortfolioId();
}
如果没有自定义反序列化和数组JSON问题,这将非常有效。但现在我必须确定“数据”的确切类型

在上述情况下,我得到
java.lang.ClassCastException:java.util.ArrayList不能转换为auto.Rest.Data

我假设我必须创建另一个数据类(例如,将有DataObject和DataArray),并像我之前在Data.class中所做的那样描述每个参数,才能完成这项工作?我想我在反序列化过程中做错了什么,但我不确定tbh在哪里

还是我错了,可以将数据作为列表调用,将数据作为同一类的对象调用


我已经为此工作了好几天(?)并且正在考虑使用泛型而不是Gson帮助,是的,我很绝望。感谢您的帮助。

如果总是有一个对象,只需添加

json.getAsJsonArray().get(0)

public class UserDeserializer implements JsonDeserializer<User> {

  private Type listType = new TypeToken<List<Data>>(){}.getType();

  @Override
  public User deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {

    User user = new User();
    JsonElement jsonElement;
    if (json.isJsonArray()) {
      jsonElement = json.getAsJsonArray().get(0);
      user.data = context.deserialize(jsonElement,listType);
//            user.data = new Gson().fromJson(jsonElement, new TypeToken<List<Data>>() {}.getType());
    } else {
      jsonElement = json.getAsJsonObject();
      user.data = context.deserialize(jsonElement, Data.class);
//            user.setData(new Gson().fromJson(jsonElement, new TypeToken<Data>() {}.getType()));
    }
    return user;
  }

}
公共类UserDeserializer实现JsonDeserializer{
私有类型listType=new-TypeToken(){}.getType();
@凌驾
公共用户反序列化(JsonElement json,类型类型,JsonDeserializationContext)引发JsonParseException{
用户=新用户();
JsonElement JsonElement;
if(json.isJsonArray()){
jsonElement=json.getAsJsonArray().get(0);
user.data=context.deserialize(jsonElement,listType);
//user.data=new Gson().fromJson(jsonElement,new TypeToken(){}.getType());
}否则{
jsonElement=json.getAsJsonObject();
user.data=context.deserialize(jsonElement,data.class);
//setData(新的Gson().fromJson(jsonElement,新的TypeToken(){}.getType());
}
返回用户;
}
}
如果有更多对象,请将字段数据更改为列表

public class UserDeserializer implements JsonDeserializer<User> {

  private Type listType = new TypeToken<List<Data>>(){}.getType();

  @Override
  public User deserialize(JsonElement json, Type type, JsonDeserializationContext context) throws JsonParseException {

    User user = new User();
    JsonElement jsonElement;
    if (json.isJsonArray()) {
      jsonElement = json.getAsJsonArray();
      user.data = context.deserialize(jsonElement,listType);
//            user.data = new Gson().fromJson(jsonElement, new TypeToken<List<Data>>() {}.getType());
    } else {
      jsonElement = json.getAsJsonObject();
      List<Data> data = new ArrayList<Data>();
      data.add(context.deserialize(jsonElement, Data.class)) ;
      user.data = data ;
//            user.setData(new Gson().fromJson(jsonElement, new TypeToken<Data>() {}.getType()));
    }
    return user;
  }

}
公共类UserDeserializer实现JsonDeserializer{
私有类型listType=new-TypeToken(){}.getType();
@凌驾
公共用户反序列化(JsonElement json,类型类型,JsonDeserializationContext)引发JsonParseException{
用户=新用户();
JsonElement JsonElement;
if(json.isJsonArray()){
jsonElement=json.getAsJsonArray();
user.data=context.deserialize(jsonElement,listType);
//user.data=new Gson().fromJson(jsonElement,new TypeToken(){}.getType());
}否则{
jsonElement=json.getAsJsonObject();
列表数据=新的ArrayList();
add(context.deserialize(jsonElement,data.class));
user.data=数据;
//setData(新的Gson().fromJson(jsonElement,新的TypeToken(){}.getType());
}
返回用户;
}
}
并将User.class字段数据更改为List

public List<Data> data;
公共列表数据;

这在kotlin语言中是一个类似的主题

如果您总是有
对象
一个元素数组
,您可以编写自定义反序列化程序,如下所示:

class OneOrElementJsonDeserializer<T> implements JsonDeserializer<T> {

    @Override
    public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        if (json instanceof JsonArray) {
            final JsonArray array = (JsonArray) json;
            final int size = array.size();
            if (size == 0) {
                return null;
            }

            return context.deserialize(array.get(0), typeOfT);
        }

        return context.deserialize(json, typeOfT);
    }
}
用法示例:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
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 java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;

public class GsonApp {

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

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

        User root = gson.fromJson(new FileReader(jsonFile), User.class);
        System.out.println(root);
    }
}
上面的代码表示下面的
JSON
有效负载:

{
  "data": [
    {
      "id": "c87ca3fe85781007869b83f"
    }
  ]
}
{
  "data": {
    "id": "c87ca3fe85781007869b83f"
  }
}
印刷品:

User{data=Data{id='c87ca3fe85781007869b83f'}}
User{data=Data{id='c87ca3fe85781007869b83f'}}
对于
object
case
JSON
payload:

{
  "data": [
    {
      "id": "c87ca3fe85781007869b83f"
    }
  ]
}
{
  "data": {
    "id": "c87ca3fe85781007869b83f"
  }
}
印刷品:

User{data=Data{id='c87ca3fe85781007869b83f'}}
User{data=Data{id='c87ca3fe85781007869b83f'}}

如果您的属性可能包含
JSON对象
多元素数组
,请参阅我对这个问题的回答。有一个实现的反序列化程序可以处理这样的情况。

{“数据”:[{“id”:“value”}}表示可以有多个id的数组。在这种情况下,您的
数据
实例是什么样子的,例如对于
{“Data”:[{“id”:“1”},{“id”:“2”}
user.Data=context.deserialize(jsoneElement,listType)无法工作,因为您正在反序列化
列表
,并试图将其分配给类型为
数据
的字段。在这种情况下,您应该执行类似于
listdatalist=context.deserialize(jsonElement,listType)的操作然后从该列表中获取一个元素(如果有的话),并将其分配给
用户。data
@Thomas这是一个类似以下内容的投资组合列表:
{“data”:[{“id”:“c87ca3fe85781007869b83f”,“template”:0,“publish”:false,“publication_at”:null,“likes”:0,“liked”:false,“comments”:0,“cells”:{“data”:[{/*something*/}]}},{/*something-something*/}]},{/*something-something*/}]},{/*something-something-something-something*/}]}
我真的希望这是可以理解的。@Thomas谢谢。我会试试这个。我能先把它分配给
user.data
然后再分配给
.getId(
来自后者?或者我必须为
列表创建相同的方法
?如果
数据可以用现成的映射进行反序列化,那么只需将数组反序列化为列表并从反序列化的元素中获取id就足够了。根据@MichałZiober的回答,我已经做了一些更正,以完成这项工作
@Override public T反序列化(JsonElement json,类型类型,JsonDeserializationContext)抛出JsonParseException{JsonElement JsonElement;if(json.isJsonArray()){JsonElement=json.getAsJsonArray().get(0);返回context.deserialize(JsonElement,类型);}else{jsonElement=json.getAsJsonObject();返回context.deserialize(jsonElement,type);//Data.class同样有效}
感谢您的回答。感谢您的回答。对于一个调用,这很好:
User responseBody=ca