在前後端資料傳輸互動中,經常會遇到字元串(String)與json,XML等格式互相轉換與解析,其中json以跨語言,跨前後端的優點在開發中被頻繁使用,基本上可以說是标準的資料交換格式。以前用fastjson比較多,最近項目使用net.sf.json包進行json格式轉換,也碰到一些問題在這裡記錄一下。
功能方面比較強大支援各種類型之間的轉換,比如:
JSONObject,JSONArray,JavaBean與json字元串互轉,List與json字元串互轉,Map與json字元串互轉,JSONArray與List互轉,JSONArray與數組互轉、XML與JSON互轉等。
java對象轉換成json時提供很多的方法進行控制,可以友善自定義資料類型和格式轉換處理。
可是Json轉換Java bean對象的時候,幾乎沒有提供什麼友善的方式。
比如:我們的代碼裡,裝置實時采集參數裡有boolean類型資料,json中是true,false類型,java bean對象中需要轉換成 float的1,0。像這樣很簡單的一個需求,結果在jsonconfig中沒有找到合适的方法,上網搜尋這方面的資料也很少,幾乎說的都是java轉json方面的内容。
經過檢視net.sf.json源代碼,發現其中實作了一系列的Morpher類進行類型轉換處理,可以以資料類型為入口,按資料類型添加處理邏輯進而進行資料類型轉換的控制。
比如我的java對象中的屬性是float類型,我自己可以實作一個自定義的float類型的Morpher進行float類型轉換。建立一個float類型轉換類BooleanToFloatMorpher ,繼承自AbstractDecimalMorpher。
package com.cnooc.common.utils;
import net.sf.ezmorph.MorphException;
import net.sf.ezmorph.object.NumberMorpher;
import net.sf.ezmorph.primitive.AbstractDecimalMorpher;
;
import net.sf.ezmorph.primitive.FloatMorpher;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
public class BooleanToFloatMorpher extends AbstractDecimalMorpher {
private float defaultValue = 0f;
public BooleanToFloatMorpher() {
}
public BooleanToFloatMorpher(float defaultValue) {
super(true);
this.defaultValue = defaultValue;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (obj == null) {
return false;
} else if (!(obj instanceof BooleanToFloatMorpher)) {
return false;
} else {
BooleanToFloatMorpher other = (BooleanToFloatMorpher)obj;
EqualsBuilder builder = new EqualsBuilder();
if (this.isUseDefault() && other.isUseDefault()) {
builder.append(this.getDefaultValue(), other.getDefaultValue());
return builder.isEquals();
} else {
return !this.isUseDefault() && !other.isUseDefault() ? builder.isEquals() : false;
}
}
}
public float getDefaultValue() {
return this.defaultValue;
}
public int hashCode() {
HashCodeBuilder builder = new HashCodeBuilder();
if (this.isUseDefault()) {
builder.append(this.getDefaultValue());
}
return builder.toHashCode();
}
public float morph(Object value) {
float result;
if(value == null){
return this.getDefaultValue();
}
if(value.toString().toLowerCase().equals("true")){
return 1f;
}
if(value.toString().toLowerCase().equals("false")){
return 0f;
}
if (this.isUseDefault()) {
result = new Float((new FloatMorpher(this.defaultValue)).morph(value));
} else {
result = new Float((new FloatMorpher()).morph(value));
}
return result;
}
public Class morphsTo()
{
Class var10000;
try {
var10000 = Class.forName("java.lang.Float");
} catch (ClassNotFoundException var4) {
throw new NoClassDefFoundError(var4.getMessage());
}
return var10000;
}
}
方法:morphsTo()
這個屬于處理的入口,資料類型是java.lang.Float時候,使用這個類進行資料轉換。
方法:public float morph(Object value)
該方法是具體的轉換邏輯,輸入值是true,false時,轉換成1,0。
最後,在調用轉換方法之前,把自定義的轉換器注冊到JSONUtils裡。
JSONUtils.getMorpherRegistry().registerMorpher(new BooleanToFloatMorpher(),true);
轉換:
config.setRootClass(MongoWits58.class);
JSONObject.toBean(data, config);
總結:
這種轉換方式簡單粗暴,不像java轉json那樣可以按屬性名稱和類型控制轉換字段,隻能按目标類的資料類型進行轉換處理,其實在源代碼中提供了源類的資料類型控制參數,不知道為啥轉換處理的時候沒有使用此參數。理想情況是能提供按參數字段名稱,源類的字段資料類型,字段名稱,目标類資料類型,字段名稱進行轉換控制。