天天看點

Json還可以這樣用

   日常項目中經常有這樣的需求,即需要幾個緊密相關的内容存儲起來,例如,xxx省xxx市xxx區等等。

例如下圖:

  這些緊密相關的内容可能會經常增加或者減少某項内容,在資料庫應用中,當然可以設計幾個字段來存儲或者設計一個專門的key-value表來存儲這些可變内容,但是對于這類不會直接用條件進行檢索的緊密關聯的内容來講,儲存在一個字段traffic_description中似乎更為妥帖一點。既然要存儲在一個字段中那麼就涉及到如何分割群組裝的問題。

  一個比較直接的做法就是使用分号對每項值進行分割存儲,這種方式屬于一種平面的結構,還有一個更好的辦法就是将這些字段組裝成一個json 字元串,格式如{\'key1\':value1,\'key2\':[\'value2\',\'value21\']},這樣就可以直接利用現成的對象存儲方式來儲存,目前就有很多第三方包對json提供了支援,如:java中提供了json-lib.jar,其他語言支援包見

www.json.org

   下面提供一種簡單的實作:

   import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import java.lang.reflect.Field;

import java.util.Collection;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import net.sf.json.JSONArray;

import net.sf.json.JSONObject;

import org.apache.commons.beanutils.BeanUtils;

import org.apache.commons.beanutils.PropertyUtils;

import org.apache.commons.lang.builder.ToStringBuilder;

import com.alibaba.common.logging.Logger;

import com.alibaba.common.logging.LoggerFactory;

/**

*

* <p>

* json 字元串生成和解析base類

* </p>

*

* @author <a href="mailto:[email protected]" mce_href="mailto:[email protected]">清虛</a>

* @since 2.0 2009-10-19上午10:42:57

*

*/

public class JsonDO {

private static final Logger log = LoggerFactory.getLogger("JsonDO");

/**

* json 屬性标注 ,表示該屬性需要放入json對象

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.FIELD)

public @interface JsonField {

}

private String value;// json字元串,一般存儲在資料庫中

/**

* 調用該方法會設定value屬性,該方法一般在儲存資料庫時調用

*

* @return the value

*/

public String getValue() {

encode();

return value;

}

/**

* 調用該方法會解析value字元串,并設定相應的java 屬性,該方法一般在從資料庫中load時調用

*

* @param value

* the value to set

*/

public void setValue(String value) {

this.value = value;

decode();

}

/**

*

*

* <p>

* 将value json中的屬性值設定到對應的java DO屬性中去,java 屬性必須有JsonField 标注才會被設定

* </p>

*

* @author <a href="mailto:[email protected]" mce_href="mailto:[email protected]">清虛</a>

* @since 2.0 2009-10-19下午02:39:56

*

*/

@SuppressWarnings("unchecked")

protected void decode() {

if (this.value == null || this.value.trim().equals("")) {

return;

}

Map<String, Class> classMap = new HashMap<String, Class>();

Field[] fs = getClass().getDeclaredFields();

for (Field f : fs) {

if (f.isAnnotationPresent(JsonField.class)) {

classMap.put(f.getName(), f.getClass());

}

}

if (classMap.isEmpty()) {

return;

}

JSONObject json = JSONObject.fromObject(this.value);

JsonDO o = (JsonDO) JSONObject.toBean(json, getClass(), classMap);

Set<String> set = classMap.keySet();

Iterator<String> it = set.iterator();

while (it.hasNext()) {

String name = it.next();

try {

Object value = PropertyUtils.getSimpleProperty(o, name);

BeanUtils.copyProperty(this, name, value);

} catch (Exception e) {

log.error("copy prorperty error src=" + this.value, e);

}

}

}

/**

*

*

* <p>

* 将JsonField 标注了的基本屬性組裝成json字元串儲存在value中

* </p>

*

* @author <a href="mailto:[email protected]" mce_href="mailto:[email protected]">清虛</a>

* @since 2.0 2009-10-19下午02:41:27

*

*/

@SuppressWarnings("unchecked")

protected void encode() {

JSONObject json = new JSONObject();

Field[] fs = getClass().getDeclaredFields();

for (Field f : fs) {

if (f.isAnnotationPresent(JsonField.class)) {

String name = f.getName();

Object value = null;

try {

value=PropertyUtils.getSimpleProperty(this, name);

//value = f.get(this);

} catch (Exception e) {

log.error("get field value failed! fieldName=" + name, e);

}

if (value == null) {

continue;

}

Class type = f.getType();

if (Collection.class.isAssignableFrom(type)) {

Collection it = (Collection) value;

for (Object v : it) {

json.accumulate(name, v);

}

} else if (type.isArray()) {

json.put(name, JSONArray.fromObject(value));

} else {

json.put(name, value);

}

}

}

this.value=json.toString();

//setValue(json.toString());

}

/*

* (non-Javadoc)

*

* @see java.lang.Object#toString()

*/

@Override

public String toString() {

return ToStringBuilder.reflectionToString(this);

}

使用方式如下:

public class TrafficDO extends JsonDO {

/**

*序列号

*/

private static final long serialVersionUID = -5673233152393642499L;

@JsonField

private String invoiceTitle; //發票擡頭

@JsonField

private String fullName; //配送人姓名

@JsonField

private String mobileTel; //配送手機号碼

@JsonField

private String province; //省

@JsonField

private String city; //市

@JsonField

private String section; //區

@JsonField

private String address; //詳細位址

@JsonField

private String post; //郵編

private int shipmentType; //配送方式

public static final int BY_MAIL_TYPE = 0; //挂号信郵寄方式

public static final int BY_NOTNEED = -1; //不需要行程單

/**

* @return the shipmentType

*/

public int getShipmentType() {

return shipmentType;

}

/**

* @param shipmentType the shipmentType to set

*/

public void setShipmentType(int shipmentType) {

this.shipmentType = shipmentType;

}

/**

* @return the fullName

*/

public String getFullName() {

return fullName;

}

/**

* @param fullName the fullName to set

*/

public void setFullName(String fullName) {

this.fullName = fullName;

}

/**

* @return the mobile

*/

public String getMobileTel() {

return mobileTel;

}

/**

* @param mobile the mobile to set

*/

public void setMobileTel(String mobile) {

this.mobileTel = mobile;

}

/**

* @return the province

*/

public String getProvince() {

return province;

}

/**

* @param province the province to set

*/

public void setProvince(String province) {

this.province = province;

}

/**

* @return the city

*/

public String getCity() {

return city;

}

/**

* @param city the city to set

*/

public void setCity(String city) {

this.city = city;

}

/**

* @return the section

*/

public String getSection() {

return section;

}

/**

* @param section the section to set

*/

public void setSection(String section) {

this.section = section;

}

/**

* @return the address

*/

public String getAddress() {

return address;

}

/**

* @param address the address to set

*/

public void setAddress(String address) {

this.address = address;

}

/**

* @return the post

*/

public String getPost() {

return post;

}

/**

* @param post the post to set

*/

public void setPost(String post) {

this.post = post;

}

/**

* 郵寄

*

* @return

*/

public boolean isMail() {

return this.shipmentType == BY_MAIL_TYPE;

}

/**

* 不需要

*

* @author qingxu

* @since 2007-10-25下午04:48:12

*

* @return

*/

public boolean isNotNeed() {

return this.shipmentType == BY_NOTNEED;

}

public String getInvoiceTitle() {

return invoiceTitle;

}

public void setInvoiceTitle(String invoiceTitle) {

this.invoiceTitle = invoiceTitle;

}

}

  @JsonField标注支援 基本類型和數組、collection類型域。

在從DB中load出traffic_description的值後

通過setValue()方法設定進去,那麼所有的json域都會被填充好。同樣的,如果填充了相應的json域,

在存儲在資料庫中時,可以調用getValue()得到字元串持久化到資料庫中。

   通過getValue()得到的字元串形式如下:

  {"section":"馬龍縣","fullName":"叮當","address":"vvvvvv","province":"雲南省","invoiceTitle":"vvvvvv","mobileTel":"136**622627","post":"310014","city":"曲靖市"}

    這種處理方式的好處是,可以友善的定義你自己要存儲的内容,你所有做的僅僅是在新增一個field,然後在上面打上@JsonField标注即可。

    而它的缺點也是明顯的,1、這種方式明顯增加了存儲内容的長度 2、由于存儲的key是屬性的名稱,如果名稱不比對也會找不到對應的值。3、如果要對其中的内容進行條件檢索,隻有進行文本比對,如果有這種需求,這種方式不推薦。

Json還可以這樣用

繼續閱讀