近日,CNBC报道称,《金融时报》援引未透露姓名的消息人士称,欧盟官员将对谷歌母公司Alphabet施加“负面影响”,并对其通过安卓手机操作系统滥用主导地位处以高达110亿美元的罚款。
作者简介
叶颖的这个贡献是叶,分享一下安卓系统中Gson的知识,大家来看看!希望大家喜欢。
叶颖是叶的博客地址:
https://www.jianshu.com/u/1d933ff900e7
前言
Json是文本形式的数据交换格式,比xml轻。解析和生成Json的方法有很多。Android平台上最常用的类库是Gson和FastJson。这里介绍Gson
Gson的GitHub主页点击这里:
https://github.com/google/gson
Gson的基本用法
Gson对象
在序列化和反序列化之前,您需要实例化一个com .google.Gson.Gson对象。有两种方法可以得到gson对象。
//通过构造函数获取
gson gson = new gson();
//通过GsonBuilder获得,可以专门配置
Gson gson = newGsonBuilder()。create();
生成Json
使用Gson,可以通过使用addProperty的四个重载方法轻松生成Json字符串
public static void main(String[]args){
JSON object JSON object = new JSON object();
jsonobject . addproperty(" String "/>
在addProperty方法的底部,调用add (string property,JsonElement value)方法,即把基本数据类型转换成jsoneElement对象,这是一个抽象类,JsonObject继承jsoneElement,我们可以通过JsonObject本身构建一个jsoneElement。
public static void main(String[]args){
JSON object JSON object = new JSON object();
jsonobject . addproperty(" String "/>
Json与数组和列表的转换
Json数组和字符串数组
public static void main(String[]args){
//Json数组转换成字符串数组
gson gson = new gson();
string JSonarray = "[" https://GitHub . com/leaves sc "、" https://www . jishu . com/u/9df 45 b 87 cfdf "、" Java "、" Kotlin "、" Git "、" GitHub "]";
String[]strings = gson . Fromjson(JSonarray,String[]。类);
System.out.println( "Json数组到字符串数组:");
for(String string : strings) {
System.out.println(字符串);
}
//将字符串数组转换为Json数组
JSON array = gson . tojson(JSON array,newTypeToken & lt字符串>() {
}.getType());
System.out.println( "n字符串数组到Json数组:");
system . out . println(JSonarray);
}
逆序的方式类似
public static void main(String[]args){
//反序列化
string userJson = " { " name ":" leaves sc "," age":24," sexual ":true } ";
gson gson = new gson();
user user = gson . fromjson(userJson,user . class);
system . out . println();
System.out.println(用户);
}
属性重命名
继续使用上一节中声明的用户类。根据User类声明的属性名,移动开发者希望接口返回的数据格式如下
{ " name ":" leaves sc "," age": 24," sexual ":true }
如果没有和服务器很好的沟通或者修改了API,接口返回的数据格式可能是这样的
{ "姓名":" leavesC ","年龄":24,"性别":真}
{“userName”:“leaves sc”,“age”:24,“sexual”:true }
如果继续使用上一节描述的方法,无疑会出现解析错误。例如
public static void main(String[]args){
//反序列化
string userJson = " { " userName ":" leaves sc "," age":24," sexual ":true } ";
gson gson = new gson();
user user = gson . fromjson(userJson,user . class);
system . out . println();
System.out.println(用户);
}
无法解析名称属性值,因此它为空
此时,为了考虑多种数据格式,有必要使用SerializedName注释。根据序列化名称的语句,序列化名称包含两个属性值,一个是字符串,另一个是字符串数组,字符串数组包含默认值
@已记录
@Retention(保留策略。RUNTIME)
@Target({ElementType。字段,元素类型。方法})
public @ interface serializedname {
string value();
string[]alternate()default { };
}
SerializedName用于指导Gson在序列化或反序列化时,在其他特殊情况下将原始属性名与属性名链接起来。
例如,修改用户类,为名称声明序列化名称注释,注释值为用户名
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassUser{
@SerializedName(“用户名”)
privateString名称;
私人占有;
privatebooleanexus;
}
在序列期间,Json格式将相应地改变
public static void main(String[]args){
//序列化
user user = new user(" leaves sc ",24,true);
gson gson = new gson();
system . out . println();
system . out . println(gson . Tojson(user));
}
反序列化时也是如此,反序列化可以解析为正确的属性值
public static void main(String[]args){
//反序列化
string userJson = " { " userName ":" leaves sc "," age":24," sexual ":true } ";
gson gson = new gson();
user user = gson . fromjson(userJson,user . class);
system . out . println();
System.out.println(用户);
}
还有一个问题没有解决。为了处理各种属性名的不一致,是否应该声明多个User类?这显然是不现实的,因此有必要为User类设置多个替代属性名,这需要使用另一个属性值,即由SerializedName注释的替代属性值。
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassUser{
@ Serialized Name(value = " USername ",alternate = { "user_name "," Name"})
privateString名称;
私人占有;
privatebooleanexus;
}
下列情况可以正确反序列化
public static void main(String[]args){
//反序列化
gson gson = new gson();
string userJson = " { " userName ":" leaves sc "," age":24," sexual ":true } ";
user user = gson . fromjson(userJson,user . class);
system . out . println();
System.out.println(用户);
userJson = " { " user _ name ":" leaves sc "," age":24," sexual ":true } ";
user = gson.fromJson(userJson,user . class);
system . out . println();
System.out.println(用户);
userJson = " { " Name ":" leaves sc "," age":24," sexual ":true } ";
user = gson.fromJson(userJson,user . class);
system . out . println();
System.out.println(用户);
}
场过滤
有时并非所有字段都需要序列化和反序列化,因此需要排除一些字段。有四种方法可以满足这一要求。
基于@Expose注释
暴露注释包含两个属性值,这两个属性值都声明了默认值。Expose的意思是“expose”,用来公开字段,序列化指定是否序列化,反序列化指定是否反序列化。如果字段没有声明Expose注释,则意味着没有序列化和反序列化,这意味着两个属性值都为false。另外,Expose注释需要和GsonBuilder构建的Gson对象一起使用才能生效。
@已记录
@Retention(保留策略。RUNTIME)
@Target({ElementType。FIELD})
public@interfaceExpose {
boolean serialize()default true;
boolean deserize()default true;
}
公开注释有四种注释值声明
@ expose (serialize = true,serialize = true)//序列化和反序列化都会生效
@ expose (serialize = false,serialize = true)//序列化时不生效,反序列化时生效
@ expose (serialize = true,serialize = false)//序列化时生效,但反序列化时不生效
@ expose (serialize = false,serialize = false)//序列化和反序列化都不起作用,就像不写注释一样。
现在看一个例子,修改用户类
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassUser{
@ expose (serialize = true,serialize = true)//序列化和反序列化都会生效
private string a;
@ expose (serialize = false,serialize = true)//序列化时不生效,反序列化时生效
private StrIng b;
@ expose (serialize = true,serialize = false)//序列化时生效,但反序列化时不生效
privateString c;
@ expose (serialize = false,serialize = false)//序列化和反序列化都不起作用,就像不写注释一样。
privateString d;
privateString e;
publicUser(字符串a,字符串b,字符串c,字符串d,字符串e){
this.a = a
this.b = b
this.c = c
this.d = d
this.e = e
}
@覆盖
publicString toString(){
返回“用户{”+
" a='"+ a + '''+
",b = ' "+b++ ' ' '+
",c = ' "+c++ ' ' '+
",d='"+ d + '''+
",e='"+ e + '''+
'}';
}
}
根据上述注释值,只有声明为“暴露”注释且序列化值为真的字段才能被序列化,只有声明为“暴露”注释且反序列化值为真的字段才能被反序列化
public static void main(String[]args){
Gson gson = newGsonBuilder()。exclude fieldswithoutexposeannotation()。create();
用户用户=新用户(“A”、“B”、“C”、“D”、“E”);
system . out . println();
system . out . println(gson . Tojson(user));
String json = "{"a":"A "、" b":"B "、" c":"C "、" d":"D "、" E ":" E " } ";
user = gson.fromJson(json,user . class);
system . out . println();
system . out . println(user . ToString());
}
基于版本
Gson提供了两个注释,@自和@至,根据版本过滤字段。@自和@至都包含一个Double属性值,用于设置版本号。既然意思是“从……”直到意味着“直到……”,应该与GsonBuilder一起使用。
@已记录
@Retention(保留策略。RUNTIME)
@Target({ElementType。字段,元素类型。类型})
public@interfaceSince {
double value();
}
@已记录
@Retention(保留策略。RUNTIME)
@Target({ElementType。字段,元素类型。类型})
public @ interfaceUntil {
double value();
}
当版本(由GsonBuilder设置的版本)大于或等于“自”属性值或小于“至”属性值时,字段将被序列化和反序列化,而没有声明注释的字段将被添加到序列化和反序列化操作中。
现在看一个例子,修改用户类
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassUser{
@自(1.4)
private string a;
@自(1.6)
private StrIng b;
@自(1.8)
privateString c;
@直到(1.6)
privateString d;
@直到(2.0)
privateString e;
publicUser(字符串a,字符串b,字符串c,字符串d,字符串e){
this.a = a
this.b = b
this.c = c
this.d = d
this.e = e
}
@覆盖
publicString toString(){
返回“用户{”+
" a='"+ a + '''+
",b = ' "+b++ ' ' '+
",c = ' "+c++ ' ' '+
",d='"+ d + '''+
",e='"+ e + '''+
'}';
}
}
public static void main(String[]args){
Gson gson = newGsonBuilder()。setVersion( 1.6)。create();
用户用户=新用户(“A”、“B”、“C”、“D”、“E”);
system . out . println();
system . out . println(gson . Tojson(user));
String json = "{"a":"A "、" b":"B "、" c":"C "、" d":"D "、" E ":" E " } ";
user = gson.fromJson(json,user . class);
system . out . println();
system . out . println(user . ToString());
}
基于访问修饰符
访问修饰符由java.lang.reflect.Modifier定义为int类型,GsonBuilder对象的excludeFieldsWithModifiers方法接收int类型可变参数,该参数指定访问修饰符字段,无需序列化和反序列化。看一个例子
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassModifierSample{
public string public field = " public ";
protected string protected field = " protected ";
private string private field = " private ";
String defaultField = " default
finalString finalField = " final
static StrIng static field = " static ";
}
public static void main(String[]args){
Gson gson = newGsonBuilder()。excludeFieldsWithModifiers(修饰符。私人,修饰词。静态)。create();
modifier sample modifier sample = new modifier sample();
system . out . println(gson . to JSON(ModifierSample));
}
基于策略
GsonBuilder类包含setexclusionstrategies(exclusionstrategy...strategies)方法,用于传入不定参数的strategy方法,用于直接排除指定的字段名或指定字段类型。看一个例子
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassStrategies{
privateString stringField
privateintintField
privatedoubledoubleField
公共策略(字符串字段、内部字段、双字段){
this.stringField = stringField
this . int field = int field;
this . double field = double field;
}
@覆盖
publicString toString(){
返回“策略{”+
" StringField = ' "+StringField+' ' '+
",intField="+ intField +
",doubleField="+ doubleField +
'}';
}
}
public static void main(String[]args){
Gson gson = newGsonBuilder()。setExclusionStrategies(new exclusionstrategy(){
@覆盖
public booleanShadeSkipfield(field Attributes field Attributes){
//排除指定的字段名
returnfieldAttributes.getName()。equals(" intField ");
}
@覆盖
public BooleanShadeSkipclass(Class & lt;?>。aClass){
//排除指定的字段类型
returnaClass.getName()。equals(double . class . GetName());
}
}).create();
战略战略=新战略战略(“stringField”,111,11.22);
system . out . println();
system . out . println(gson . Tojson(strategies));
string JSON = " { " string field ":" string field "," intField":111," double field ":11.22 } ";
strategies = gson.fromJson(json,strategies . class);
system . out . println();
system . out . println(strategies);
}
字段名称为“国际字段”且字段类型为双精度的字段将被排除
方法在序列化和反序列化期间生效。如果只想在一种情况下指定排除策略或单独指定排除策略,可以使用以下两种方法
addSerializationExclusionStrategy(ExclusionStrategy strategy);addDeserializationExclusionStrategy(ExclusionStrategy strategy);个性化设置
输出null
对于Gson,如果在序列化期间属性值为null,则该字段将不参与序列化。如果您想显示和输出该字段,您可以通过GsonBuilder进行配置
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassStrategies{
privateString stringField
privateintintField
privatedoubledoubleField
}
public static void main(String[]args){
Gson gson = newGsonBuilder()
。serializeNulls() //输出null
。create();
战略战略=新战略战略(null,24,22.333);
system . out . println();
system . out . println(gson . Tojson(strategies));
}
打印格式Json
默认序列化的Josn字符串不是很直观,可以选择打印格式
public static void main(String[]args){
Gson gson = newGsonBuilder()
。serializeNulls() //输出null
。setPrettyPrinting() //打印格式
。create();
战略战略=新战略战略(null,24,22.333);
system . out . println();
system . out . println(gson . Tojson(strategies));
}
格式化时间
Gson还可以格式化时间值
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassStrategies{
privateDate日期;
privateDate日期2;
公共策略(日期日期,日期日期2){
this.date = date
this . date 2 = date 2;
}
@覆盖
publicString toString(){
简单日期格式简单日期格式=新简单日期格式(“yyyy-MM-dd HH:mm:ss:SSS”,区域设置。中国);
返回“策略{”+
" date = "+SimpleDateformat . format(date)+
",date 2 = "+SimpleDateformat . format(date 2)+
'}';
}
}
public static void main(String[]args){
Gson gson = newGsonBuilder()
。setPrettyPrinting() //打印格式
。设置日期格式(“yyyy-mm-DD hh:mm:ss:SSS”)//格式
更改时间
。create();
date date = new date();
strategies strategies = newStrategies(date,new date(date . gettime()+1000000));
system . out . println();
system . out . println(gson . Tojson(strategies));
String json = "{n"+
" "日期":" 2018-03-17 19:38:50:033 ",n"+
" "日期2": "2018-03-17 19:55:30:033"n"+
"}";
system . out . println();
system . out . println(gson . Fromjson(JSON,strategies . class));
}
类型适配器
TypeAdapter是一个泛型抽象类,用于接管某个类型的序列化和反序列化过程。它包含两个抽象方法,分别用于定制序列化和反序列化过程
publicatabstractvoitwrite(JsonWriter var1,T var2)throwsionexception;
public abstract read(JSonreader var1)throwsio exception;
让我们举一个简单的例子
/**
*作者:chenZY
*时间:2018年3月17日18: 32
*描述:https://github.com/leavesC
*/
publicclassUser{
privateString名称;
私人占有;
privatebooleanexus;
publicUser(){
}
publicUser(字符串名称,intage,booleanex){
this.name = name
this.age = age
this.sex = sex
}
@覆盖
publicString toString(){
返回“用户{”+
" name='"+ name + '''+
",age="+ age +
“,sex =+sex+
'}';
}
}
子类类型适配器被定义为接管用户类的序列化和反序列化。
这里设置了当用户类被序列化时,Json中的键值以大写字母开始,并且在反序列化过程中支持两种不同的Json样式,“名称”和“名称”
publicClassUserTypeAdapter extendsTypeAdapter & lt;用户>。{
@覆盖
public void write(JsonWriter JsonWriter,User user)throwsIOException {
//开始对象的流序列化
jsonwriter . BeginObject();
//将Json的键值指定为大写字母的开头
jsonWriter.name( "Name ")。value(user . GetName());
jsonWriter.name("年龄")。value(user . GetAge());
jsonWriter.name( "Sex ")。value(user . issex());
//流序列化结束
jsonwriter . endobject();
}
@覆盖
public user read(JSonreader JSonreader)throwsio exception {
user user = NewUser();
//流反序列化开始
jsonreader . BeginObject();
while(jsonReader.hasNext()) {
switch(jsonReader.nextName()) {
//大写字母在这种情况下是合法的
大小写“名称”:
案例“名称”:
user . setname(JSonreader . NextString());
打破;
案例“年龄”:
user . setage(jsonreader . nextint());
打破;
案例“性”:
user . setsex(jsonreader . nextboolean());
打破;
}
}
//流反序列化结束
jsonreader . endobject();
returnuser
}
}
public static void main(String[]args){
Gson gson = newGsonBuilder()。registerTypeAdapter(User.class,newUserTypeAdapter())。create();
user user = new user(" leaves sc ",24,true);
system . out . println();
system . out . println(gson . Tojson(user));
string JSON = " { " Name ":" leaves sc "," age":24," sexual ":true } ";
user = gson.fromJson(json,user . class);
system . out . println();
System.out.println(用户);
}
您可以看到用户类根据预定义的策略完成序列化和反序列化
JsonSerializer和JSON serializer
TypeAdapter接管序列化和反序列化操作。事实上,Gson还提供了一个只接管序列化过程的接口,即JsonSerializer。看一个例子
public static void main(String[]args){
Gson gson = newGsonBuilder()。registerstypedadapter(user . class,newJsonSerializer & lt用户>。() {
@覆盖
publicJsonElement序列化(用户用户,类型,JsonSerializationContext JsonSerializationContext){
JSON object JSON object = new JSON object();
jsonObject.addProperty( "NameHi ",user . GetName());
jsonObject.addProperty( "Sex ",user . issex());
jsonObject.addProperty( "Age ",user . GetAge());
returnjsonoobject;
}
}).create();
user user = new user(" leaves sc ",24,true);
system . out . println();
system . out . println(gson . Tojson(user));
}
相应地,JsonDeserializer接口为反序列化提供了一个接口
public static void main(String[]args){
Gson gson = newGsonBuilder()。注册类型适配器(User.class,newJsonDeserializer & lt用户>。() {
@覆盖
publicUser反序列化(JsonElement jsonElement,类型,JSondeSerializationContext JSondeSerializationContext)throwsjssonparseException {
JsonObject JsonObject = jsonelement . getasjsonobject();
字符串名称= null
//支持用户名和名称
if(JSonobject . has(" UserName ")){
name = jsonObject.get( "userName ")。getAsString();
} else if(JSonobject . has(" name ")){
name = jsonObject.get( "name ")。getAsString();
}
intage = jsonObject.get( "age ")。getAsInt();
booleansex = jsonObject.get( "sex ")。getasboilen();
returnnewUser(姓名、年龄、性别);
}
}).create();
string JSON = " { " userName ":" leaves sc "," sexual ":true," age ":24 } ";
User user = gson.fromJson(json,user . class);
system . out . println();
System.out.println(用户);
JSON = " { " name ":" leaves sc "," sexual ":true," age ":24 } ";
user = gson.fromJson(json,user . class);
system . out . println();
System.out.println(用户);
}
这里有个麻烦,就是在使用TypeAdapter、JsonSerializer、jsondserializer的时候,总是需要调用registerTypeAdapter方法进行注册,那么有没有更简单的注册方法呢?
是的,Gosn还为简单声明提供了另一个注释@JsonAdapter。与此类似,声明User类的序列化或反序列化由UserTypeAdapter完成,注释的优先级高于registerTypeAdapter方法
@ JSonadapter(UserTypeAdapter . class)
publicclassUser{
}
TypeAdapterFactory
TypeAdapterFactory是用于创建类型适配器的工厂类。通过参数TypeToken可以找到相应的类型适配器。如果不是,则返回null,序列化和反序列化由Gson默认处理方法执行;否则,typeadapters由用户预定义。
Gson gson = newGsonBuilder()。registertypedadapterfactory(new typedadapterfactory(){
@覆盖
公共<。T>。TypeAdapter<。T>。创建(Gson gson,TypeToken & ltT>。typeToken){
//如果Gson需要与User类相关的TypeAdapter,它会返回我们自己定义的TypeAdapter对象
if(typeToken.getType()。getTypeName()。equals(user . class . gettypename()){
返回(TypeAdapter & ltT>。)NewUsertypeAdapter();
}
//如果找不到,则返回null
returnnull
}
}).create();
总结
这篇文章好像有点太长了?Gson的知识点介绍到这里差不多了,以后如果发现新内容我会继续补充,现在就做吧。
我的短簿地址如下:
https://www.jianshu.com/u/9df45b87cfdf
我的github地址如下:
https://github.com/leavesC
1.《gson Android Gson使用详解》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《gson Android Gson使用详解》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/junshi/990980.html