使用GSON为BasicNameValuePairs列表创建自定义序列化器-反序列化器

8

我正在尝试为一些BasicNameValuePair对象列表实现自定义gson序列化器/反序列化器。

我在这里看到了部分解决方案代码(用于序列化): 如何让Gson序列化基本名称值对的列表?

然而,我也想实现反序列化,我尝试了一下,代码在这里:

package dto;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.message.BasicNameValuePair;


import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;


    public class KeyValuePairSerializer extends TypeAdapter<List<BasicNameValuePair>> {
        @Override
        public void write(JsonWriter out, List<BasicNameValuePair> data) throws IOException {
            out.beginObject();
            for(int i=0; i<data.size();i++){
                out.name(data.get(i).getName());
                out.value(data.get(i).getValue());
            }
            out.endObject();
        }

        @Override
        public List<BasicNameValuePair> read(JsonReader in) throws IOException {
            ArrayList<BasicNameValuePair> list=new ArrayList<BasicNameValuePair>();
             in.beginObject();
             while (in.hasNext()) {
               String key = in.nextName();
               String value = in.nextString();
               list.add(new BasicNameValuePair(key,value));
             }  
             in.endObject();   
             return list;
        }

}

初始化并填充列表的代码

ArrayList<BasicNameValuePair> postParameters=new ArrayList<BasicNameValuePair>();
postParameters.add(new BasicNameValuePair("some_key","some_value"));

这里是使用新的KeyValuePairSerializer类的代码:

        GsonBuilder gsonBuilder= new GsonBuilder();
        gsonBuilder.registerTypeAdapter(KeyValuePairSerializer.class, new KeyValuePairSerializer());
        Gson gson1=gsonBuilder.create();

        //serialization works just fine in the next line
        String jsonUpdate=gson1.toJson(postParameters, KeyValuePairSerializer.class);


        ArrayList<BasicNameValuePair> postParameters2 = new ArrayList<BasicNameValuePair>();
        //postParameters2 = gson1.fromJson(jsonUpdate, KeyValuePairSerializer.class); //? how to cast properly
        //deserialization throws an error, it can't cast from ArrayList<BasicNameValuePair> to KeyValuePairSerializer
        gson1.fromJson(jsonUpdate, KeyValuePairSerializer.class);

问题是它在最后抛出了一个异常,我不知道问题具体在哪里,也不确定如何编写最后一行以在新的postParameters2 ArrayList中获取结果。
4个回答

9

以下内容摘自GSON集合示例

GsonBuilder gsonBuilder= new GsonBuilder();
gsonBuilder.registerTypeAdapter(KeyValuePairSerializer.class, new KeyValuePairSerializer());
Gson gson1=gsonBuilder.create();

Type collectionType = new TypeToken<ArrayList<BasicNameValuePair>>(){}.getType();
ArrayList<BasicNameValuePair> postParameters2 = gson1.fromJson(jsonUpdate, collectionType);

做这样一件事情将忽略我新定义的类“KeyValuePairSerializer”,并且不会调用重写的方法:“读取”。 - Arise
实际上,如果您像问题中所做的那样调用registerTypeAdapter(),它就不会忽略它。 - Nachi
似乎不是这样。registerTypeAdapter 似乎只对序列化器起作用,而不是反序列化器。 - Arise

2

registerTypeAdapter似乎只适用于序列化器,而不适用于反序列化器。

唯一调用KeyValuePairSerializer的重写read函数的方法是调用:gson1.fromJson(jsonUpdate, KeyValuePairSerializer.class);而不在变量中保存结果值。虽然它可以正常处理函数,但它会在gson类中抛出错误,因为它无法将ArrayList强制转换为KeyValuePairSerializer。我有点明白为什么(可能是擦除),只是不知道如何正确地做。

无论如何,我找到了一个解决这个问题的变通方法。似乎可以通过注册gson对象并调用registerTypeAdapter,然后使用gson1.toJson(Object src, Type typeOfSrc)gson1.fromJson(String json,Class <T> classOfT)来简化反序列化:

KeyValuePairSerializer k= new KeyValuePairSerializer();
parametersList = (ArrayList<BasicNameValuePair>)k.fromJson(jsonUpdate);

0

JsonObject和NameValuePair的行为方式类似于字典,如果使用情况相似,我认为您不需要将一个转换为另一个。此外,JsonObject使您更轻松地处理值(而不是通过循环遍历值对数组来查找所需键的值,JsonObject的行为方式类似于Map,您可以直接调用键名并返回所需属性):

jsonObject.get("your key").getAsString(); (getAsBoolean(), getAsInt(), etc).

针对您的情况,我会从您的字符串、响应或流中创建一个JsonObject,然后像上面展示的那样将其作为映射访问。
JsonParser parser = new JsonParser();
JsonObject o = (JsonObject)parser.parse("your json string");

-1

我按照这篇博客 GSON集合示例 进行了跟随。 链接简单易懂,易于实现。

public class TimeSerializer implements JsonSerializer<time> {

    /**
     * Implementing the interface JsonSerializer.  
     * Notice that the the interface has a generic
     * type associated with it.  
     * Because of this we do not have ugly casts in our code.
     * {@inheritDoc}
     */
    public JsonElement serialize(
                   final Time time, 
                   final Type type,
                   final JsonSerializationContext jsonSerializationContext) {

        /** 
         * Returning the reference of JsonPremitive 
         * which is nothing but a JSONString.
         * with value in the format "HH:MM"
         */
        return new JsonPrimitive(String.format("%1$02d:%2$02d", 
                              time.getHour(), time.getMinute()));
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接