GSON反序列化字符串或字符串数​​组 [英] GSON Deserialize String or String Array

查看:130
本文介绍了GSON反序列化字符串或字符串数​​组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将包含0的对象反序列化到许多可以包含字符串或特定值的字符串数组的对象时,我遇到了一些麻烦。



例如JSON

  {
name:process name,
tasks:[ {
name:task 1,
fields:[{
name:field 1,
value:123abc

$ name b $ b $ value $ b $ name
$ b $ value



$ b $ ]
},
{
name:task 2,
fields:[]
}]
}

我有一个Java实体设置来匹配这样的结构:

  public class Process {
public Process(){}

public String name;
public Task []任务;


public class Task {
public Task(){}

public String name;
public Field []字段;
}

public class Field {
public Field()field;

公共字符串名称;
public String value;
}

我反序列化如下:

  static< T> T提取(MyHttpRequest请求,Class< T>实体)
{
字符串响应= sendRequestAndParse(请求);
if(response == null){
log.debug(String.format(API response was null%n)));
返回null;
}

GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
返回gson.fromJson(response,entity);





$ b我使用动态类型,因为除了Process之外还有其他一些实体,使用相同的方法。但我无法弄清楚如何处理字段值可以是字符串数组的字符串的情况。可能最简单的选择是使用自定义序列化器和反序列化器,并将 value 字符串到 List< String> 这里有一些基本的想法解决方案:

  private static class MyJsonAdapter实现了JsonSerializer< List< String>> ;, 
JsonDeserializer< List< String> ;> {

@Override
public JsonElement serialize(List< String> list,Type t,
JsonSerializationContext jsc){
if(list.size() == 1){
return jsc.serialize(list.get(0));
} else {
return jsc.serialize(list);
}
}
@Override
public List< String> deserialize(JsonElement json,Type typeOfT,
JsonDeserializationContext jsc)
throws JsonParseException {
List< String>结果;

if(json.isJsonArray()){
result = jsc.deserialize(json,typeOfT);
} else {
result = new ArrayList<>();
result.add((String)jsc.deserialize(json,String.class));
}
返回结果;


$ / code>

和字段POJO

  public static class Field {
public String name;

//使用@JsonAdapter(MyJsonAdapter.class)
//或在
中注册序列化器和反序列化器// new GsonBuilder()。registerTypeAdapter(new MyJsonAdapter())
@JsonAdapter(MyJsonAdapter.class)
public List< String>值; //需要将值类型更改为列表
}

如果您可以从Gson切换到Jackson,则可以使用1行代码反序列化功能.ACCEPT_SINGLE_VALUE_AS_ARRAY 来解决此问题。


I've had some trouble deserializing an object that contains 0 to many child objects that can either contains a string or a string array for a particular value.

Here's an example JSON

{
"name": "process name",
"tasks": [{
        "name": "task 1",
        "fields": [{
                "name": "field 1",
                "value": "123abc"
            },
            {
                "name": "field 2",
                "value": ["value 1", "value 2"]
            }
        ]
    },
    {
        "name": "task 2",
        "fields": []
    }]
}

I have a Java entity setup to match this structure like this:

public class Process {
    public Process() {}

    public String name;
    public Task[] tasks;
}

public class Task {
    public Task() {}

    public String name;
    public Field[] fields;
}

public class Field {
    public Field() field;

    public String name;
    public String value;
}

And I deserialize like such:

static <T> T fetch(MyHttpRequest request, Class<T> entity)
{
    String response = sendRequestAndParse(request);
    if (response == null) {
        log.debug(String.format("API response was null %n)"));
        return null;
    }

    GsonBuilder gsonBuilder = new GsonBuilder();
    Gson gson = gsonBuilder.create();
    return gson.fromJson(response, entity);
}

I use dynamic types because there's a number of other entities other than Process that I use this same method for. But I can't figure out how to handle the case where the field value can be either a string to an array of string. Any pointers would be appreciated.

解决方案

Probably the most simple option is to use custom serializer and deserializer and change value type from String to List<String> Here is basic idea how you can solve this:

private static class MyJsonAdapter implements JsonSerializer<List<String>>,
        JsonDeserializer<List<String>>{

    @Override
    public JsonElement serialize(List<String> list, Type t,
                                 JsonSerializationContext jsc) {
        if (list.size() == 1) {
            return jsc.serialize(list.get(0));
        } else {
            return jsc.serialize(list);
        }
    }
    @Override
    public List<String> deserialize(JsonElement json, Type typeOfT,
                                    JsonDeserializationContext jsc) 
            throws JsonParseException {
        List<String> result;

        if (json.isJsonArray()) {
            result = jsc.deserialize(json, typeOfT);
        }else {
            result  =  new ArrayList<>();
            result.add((String) jsc.deserialize(json, String.class));
        }
        return result;
    }
}

And Field POJO

public static class Field {
    public String name;

    // Use @JsonAdapter(MyJsonAdapter.class)
    // or register serializer and deserializer in
    // new GsonBuilder().registerTypeAdapter(new MyJsonAdapter())
    @JsonAdapter(MyJsonAdapter.class)
    public List<String> value; // need to change value type to list
}

Ps. If you could switch to Jackson from Gson, this problem could be solved with 1 line of code DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY

这篇关于GSON反序列化字符串或字符串数​​组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆