01-Android 序列化与反序列化
1. 背景
在日常开发过程中,经常遇到程序读取文件,将文件数据转换为对象,程序通过对象传输数据,或者通过对象读取数据。同时也会经常遇到对象数据写入文件操作。
如果采用常规的文件读写,然后再进行赋值;那么将耗费很多时间码代码实现,同时,如果在文件参数较多的情况下,采用常规操作将是一个重大工程量。囧o(╯□╰)o
那么软件前辈经过日夜奋进,不断创新,总结开发出很多优秀的反序列化及序列化工具/sdk/库,如下图所示
通过序列化&反序列化sdk,大大提高软件操作文件效率。
2. 方案
2.1 json
推荐方案:阿里的 fastjson
2.1.1 fastjson
Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。
Android使用要点:
- gradle导入
implementation 'com.alibaba:fastjson:1.1.71.android'
- 反序列化:
> > 示例json:
{"id":"12345678","version":"202311111","code":"100001","data":[{"name": "MSG_P1","value":"610000","count":1,"accuracy":1},{"name": "MSG_P2","value":"5 15 25 35 45 55 65 75 85 95 105 115 125 135 145 155 165 175 185 195 205 215 225 235","count":24,"accuracy":10}]
}
> > 创建对象
package com.auto.utils
import com.alibaba.fastjson.annotation.JSONType;import java.util.ArrayList;
import java.util.List;@JSONType(orders={"id","version","code","data"}) //序列化、反序列化顺序
public class JsonMsg {private String id;private String version;private String code;private List<JsonData> data= new ArrayList<>();public void setId(String id) {this.id= id;}public void setVersion(String version) {this.version= version;}public void setCode(String code) {this.code= code;}public void setJsonData(List<JsonData> data) {this.data= data;}public String getId() {return id;}public String getVersion() {return version;}public String getCode() {return code;}public List<JsonData> getJsonData() {return data;}
}
package com.auto.utils;import com.alibaba.fastjson.annotation.JSONType;@JSONType(orders={"name","value","count","accuracy"})//序列化、反序列化顺序
public class JsonData {private String name;private String value;private int count;private int accuracy;public void setName(String name) {this.name = name;}public void setValue(String value) {this.value = value;}public void setCount(int count) {this.count = count;}public void setAccuracy(int accuracy) {this.accuracy = accuracy;}public String getName() {return name;}public String getValue() {return value;}public int getCount() {return count;}public int getAccuracy() {return accuracy;}
}
> > 接口: JSON.parseObject
方法原型:
public static final <T> T parseObject(String text, Class<T> clazz) {return parseObject(text, clazz, new Feature[0]);
}
> > 使用://伪代码
private JsonMsg jsonMsg;...try {String json_str = loadJSONFromAsset(mContext,"test");JSONObject jsonObject = JSON.parseObject(json_str, Feature.OrderedField);//if(jsonObject instanceof JSONObject) {jsonMsg = JSON.parseObject(jsonObject.toJSONString(),JsonMsg .class);}else{Log.e(TAG,"jsonObject is not JSONObject.");}}catch (Exception e){e.printStackTrace();
}/
* load json file from assset.
* @param context
* @param fileName
* @return
*/
public static synchronized String loadJSONFromAsset(Context context,String fileName) {String json = null;try {InputStream is = context.getAssets().open(fileName + ".json");int size = is.available();byte[] buffer = new byte[size];is.read(buffer);is.close();json = new String(buffer, "UTF-8");} catch (IOException ex) {ex.printStackTrace();return null;}return json;
}
- 序列化
>> 接口 : JSON.toJSONString
方法原型:
public static final String toJSONString(Object object) {return toJSONString(object, SerializeConfig.globalInstance, null, null, DEFAULT_GENERATE_FEATURE);
}/* @since 1.2.11*/
public static final String toJSONString(Object object, SerializerFeature... features) {return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
}public static final String toJSONString(Object object, int defaultFeatures, SerializerFeature... features) {return toJSONString(object, SerializeConfig.globalInstance, null, null, defaultFeatures, features);
}/* @since 1.1.14*/
public static final String toJSONStringWithDateFormat(Object object, String dateFormat,SerializerFeature... features) {return toJSONString(object, SerializeConfig.globalInstance, null, dateFormat, DEFAULT_GENERATE_FEATURE, features);
}public static final String toJSONString(Object object, SerializeFilter filter, SerializerFeature... features) {return toJSONString(object, SerializeConfig.globalInstance, new SerializeFilter[] {filter}, null, DEFAULT_GENERATE_FEATURE, features);
}public static final String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features) {return toJSONString(object, SerializeConfig.globalInstance, filters, null, DEFAULT_GENERATE_FEATURE, features);
}public static final String toJSONString(Object object, SerializeConfig config, SerializerFeature... features) {return toJSONString(object, config, null, null, DEFAULT_GENERATE_FEATURE, features);
}public static final String toJSONString(Object object, SerializeConfig config, SerializeFilter filter,SerializerFeature... features) {return toJSONString(object, config, new SerializeFilter[] {filter}, null, DEFAULT_GENERATE_FEATURE, features);
}public static final String toJSONString(Object object, SerializeConfig config, SerializeFilter[] filters,SerializerFeature... features) {return toJSONString(object, config, filters, null, DEFAULT_GENERATE_FEATURE, features);
}public static final String toJSONStringZ(Object object, SerializeConfig mapping, SerializerFeature... features) {return toJSONString(object, SerializeConfig.globalInstance, null, null, 0, features);
}
> > 使用:
/* //先执行static代码块,再执行该方法* //是否输出值为null的字段,默认为false* JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteMapNullValue.getMask();* //数值字段如果为null,输出为0,而非null* JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNullNumberAsZero.getMask();* //List字段如果为null,输出为[],而非null* JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNullListAsEmpty.getMask();* //字符类型字段如果为null,输出为 "",而非null* JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteNullStringAsEmpty.getMask()*/
JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.WriteMapNullValue.mask;
Log.e(TAG,"class -> json:" + JSON.toJSONString(jsonMsg));//jsonMsg 在反序列化中有定义
saveJSONtoStorage(FilesUtils.getJsonFile(),JSON.toJSONString(jsonMsg));/* saveJSONtoStorage* @param filePath* @param jsonString* @return*/
public static synchronized void saveJSONtoStorage(String filePath,String jsonString) {String json = null;//TODOtry {File file = new File(filePath);if (!file.exists()) {file.createNewFile();} else {return;}}catch (Exception e){e.printStackTrace();return;}try {if(filePath == null){Log.e(TAG,"saveJSONtoStorage filePath is null");return;}File file = new File(filePath);FileWriter fw = null;if (file.exists()) {fw = new FileWriter(file, true);} else {fw = new FileWriter(file, false);}fw.write(String.format("%s", jsonString));fw.write(13);fw.write(10);fw.flush();fw.close();} catch (Throwable ex) {ex.printStackTrace();}
}
2.1.2 jackson
//TODO
2.2 xml
推荐方案:jackson-dataformat-xml
Android使用步骤:
- gradle导入:
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.14.2'implementation 'javax.xml.stream:stax-api:1.0-2'
- xml文件示例:
<?xml version="1.0" encoding="utf-8"?>
<XmlMsg><id>12345678</vehicleID><vcuVersion>202311111</vcuVersion><checkCode>100001</checkCode><xmlDataList><xmlData><name>MSG_P1</name><value>610000</value><count>1</count><accuracy>1</accuracy></xmlData><xmlData><name>MSG_P2</name><value>5 15 25 35 45 55 65 75 85 95 105 115 125 135 145 155 165 175 185 195 205 215 225 235</value><count>24</count><accuracy>10</accuracy></xmlData></xmlDataList>
</XmlMsg>
- 创建对象
package com.auto.utils
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;import java.util.ArrayList;
import java.util.List;@JacksonXmlRootElement(localName = "XmlMsg")
@JsonPropertyOrder({"id","version","code","data"}) //序列化、反序列化顺序
public class XmlMsg {@JacksonXmlProperty(localName = "id")private String id;@JacksonXmlProperty(localName = "version")private String version;@JacksonXmlProperty(localName = "code")private String code;@JacksonXmlElementWrapper(localName = "xmlDataList")@JacksonXmlProperty(localName = "xmlData")private List<xmlData> data= new ArrayList<>();public void setId(String id) {this.id= id;}public void setVersion(String version) {this.version= version;}public void setCode(String code) {this.code= code;}public void setJsonData(List<JsonData> data) {this.data= data;}public String getId() {return id;}public String getVersion() {return version;}public String getCode() {return code;}public List<JsonData> getJsonData() {return data;}
}
package com.auto.utils;import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;@JsonPropertyOrder({"name", "value", "count","accuracy"})//序列化、反序列化顺序
public class JsonData {@JacksonXmlProperty(localName = "name")private String name;@JacksonXmlProperty(localName = "value")private String value;@JacksonXmlProperty(localName = "count")private int count;@JacksonXmlProperty(localName = "accuracy")private int accuracy;public void setName(String name) {this.name = name;}public void setValue(String value) {this.value = value;}public void setCount(int count) {this.count = count;}public void setAccuracy(int accuracy) {this.accuracy = accuracy;}public String getName() {return name;}public String getValue() {return value;}public int getCount() {return count;}public int getAccuracy() {return accuracy;}
}
- 序列化&反序列化
try {//XNL反序列化为对象AssetManager am = context.getResources().getAssets();InputStream in = am.open( "test" + ".xml");ObjectMapper xmlMapper = XmlMapper.builder(new XmlFactory(new WstxInputFactory(), new WstxOutputFactory())).build();XmlMsg xmlMsg = xmlMapper.readValue(in,XmlMsg .class);//对象序列化为XMLxmlMapper.enable(SerializationFeature.INDENT_OUTPUT);xmlMapper.writeValue(new File(FilesUtils.getXmlFile()), xmlMsg );}catch (Exception e){e.printStackTrace();
}