Retrofit使用配合GSON

在前面的这篇文章中Android开发的5个神器中,推荐了Retrofi库,这是一个网络请求库,默认是使用Gson解析JSON数据。

Gson解析JSON数据,默认是把JSON的字段名和java对象的变量对应。如果不一样,可以用Annotation声明对应的JSON字段名,如下:

public class User {
    @SerializedName("userid")
    public String uid;

    @SerializedName("username")
    public String name;
}

对应的Json就是这样的:

{
    "userid": 123;
    "username": "Jack"
}

还有一些控制Java对象中的成员是否需要序列化的方法。 * transient关键字,可以控制不进行序列化和反序列化JSON * @Expose可以精细控制序列化和反序列化 public class Account { @Expose(deserialize = false) private String accountNumber;

        @Expose
        private String iban;

        @Expose(serialize = false)
        private String owner;

        @Expose(serialize = false, deserialize = false)
        private String address;

        private String pin;
    }

配置使用了@Expose标签,需要显式配置Gson,如下:

    final GsonBuilder builder = new GsonBuilder();
    builder.excludeFieldsWithoutExposeAnnotation();
    final Gson gson = builder.create();

详情可以参考这里GSON ANNOTATIONS EXAMPLE

另外,很多服务器返回的JSON的数据中,经常会包含一些通用的状态信息,然后把真正的数据放在一个子JSON中,如下:

{
    'status': 'OK',
    'reason': 'Everything was fine',
    'content': {
         < some data here >
    }
}

真正的内容在'content'字段中,解决的方法,自定义一个JsonDeserializer,如下:

class MyDeserializer<T> implements JsonDeserializer<T>
{
    @Override
    public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
        throws JsonParseException
    {
        // Get the "content" element from the parsed JSON
        JsonElement content = je.getAsJsonObject().get("content");

        // Deserialize it. You use a new instance of Gson to avoid infinite recursion
        // to this deserializer
        return new Gson().fromJson(content, type);

    }
}

使用的时候如下:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Content.class, new MyDeserializer<Content>())
    .registerTypeAdapter(DiffContent.class, new MyDeserializer<DiffContent>())
    .build();

解决方法参考自StackOverflow