Json还可以这样用

日常项目中经常有这样的需求,即需要几个紧密相关的内容存储起来,例如,xxx省xxx市xxx区等等。

 

例如下图:

  

 

  这些紧密相关的内容可能会经常增加或者减少某项内容,在数据库应用中,当然可以设计几个字段来存储或者设计一个专门的key-value表来存储这些可变内容,但是对于这类不会直接用条件进行检索的紧密关联的内容来讲,保存在一个字段traffic_description中似乎更为妥帖一点。既然要存储在一个字段中那么就涉及到如何分割和组装的问题。

 

  一个比较直接的做法就是使用分号对每项值进行分割存储,这种方式属于一种平面的结构,还有一个更好的办法就是将这些字段组装成一个json 字符串,格式如{'key1':value1,'key2':['value2','value21']},这样就可以直接利用现成的对象存储方式来保存,当前就有很多第三方包对json提供了支持,如:java中提供了json-lib.jar,其他语言支持包见 www.json.org

 

   下面提供一种简单的实现:

  

[java]  view plain copy print ?
  1. import java.lang.annotation.ElementType;  
  2. import java.lang.annotation.Retention;  
  3. import java.lang.annotation.RetentionPolicy;  
  4. import java.lang.annotation.Target;  
  5. import java.lang.reflect.Field;  
  6. import java.util.Collection;  
  7. import java.util.HashMap;  
  8. import java.util.Iterator;  
  9. import java.util.Map;  
  10. import java.util.Set;  
  11. import net.sf.json.JSONArray;  
  12. import net.sf.json.JSONObject;  
  13. import org.apache.commons.beanutils.BeanUtils;  
  14. import org.apache.commons.beanutils.PropertyUtils;  
  15. import org.apache.commons.lang.builder.ToStringBuilder;  
  16. import com.alibaba.common.logging.Logger;  
  17. import com.alibaba.common.logging.LoggerFactory;  
  18. /** 
  19.  * 
  20.  * <p> 
  21.  * json 字符串生成和解析base类 
  22.  * </p> 
  23.  * 
  24.  * @author <a href="mailto:qingxu@taobao.com" mce_href="mailto:qingxu@taobao.com">清虚</a> 
  25.  * @since 2.0 2009-10-19上午10:42:57 
  26.  * 
  27.  */  
  28. public class JsonDO {  
  29.     private static final Logger log = LoggerFactory.getLogger("JsonDO");  
  30.     /** 
  31.      * json 属性标注 ,表示该属性需要放入json对象 
  32.      */  
  33.     @Retention(RetentionPolicy.RUNTIME)  
  34.     @Target(ElementType.FIELD)  
  35.     public @interface JsonField {  
  36.     }  
  37.     private String value;// json字符串,一般存储在数据库中  
  38.     /** 
  39.      * 调用该方法会设置value属性,该方法一般在保存数据库时调用 
  40.      * 
  41.      * @return the value 
  42.      */  
  43.     public String getValue() {  
  44.         encode();  
  45.         return value;  
  46.     }  
  47.     /** 
  48.      * 调用该方法会解析value字符串,并设置相应的java 属性,该方法一般在从数据库中load时调用 
  49.      * 
  50.      * @param value 
  51.      *            the value to set 
  52.      */  
  53.     public void setValue(String value) {  
  54.         this.value = value;  
  55.         decode();  
  56.     }  
  57.     /** 
  58.      * 
  59.      * 
  60.      * <p> 
  61.      * 将value json中的属性值设置到对应的java DO属性中去,java 属性必须有JsonField 标注才会被设置 
  62.      * </p> 
  63.      * 
  64.      * @author <a href="mailto:qingxu@taobao.com" mce_href="mailto:qingxu@taobao.com">清虚</a> 
  65.      * @since 2.0 2009-10-19下午02:39:56 
  66.      * 
  67.      */  
  68.     @SuppressWarnings("unchecked")  
  69.     protected void decode() {  
  70.         if (this.value == null || this.value.trim().equals("")) {  
  71.             return;  
  72.         }  
  73.         Map<String, Class> classMap = new HashMap<String, Class>();  
  74.         Field[] fs = getClass().getDeclaredFields();  
  75.         for (Field f : fs) {  
  76.             if (f.isAnnotationPresent(JsonField.class)) {  
  77.                 classMap.put(f.getName(), f.getClass());  
  78.             }  
  79.         }  
  80.         if (classMap.isEmpty()) {  
  81.             return;  
  82.         }  
  83.         JSONObject json = JSONObject.fromObject(this.value);  
  84.         JsonDO o = (JsonDO) JSONObject.toBean(json, getClass(), classMap);  
  85.         Set<String> set = classMap.keySet();  
  86.         Iterator<String> it = set.iterator();  
  87.         while (it.hasNext()) {  
  88.             String name = it.next();  
  89.             try {  
  90.                 Object value = PropertyUtils.getSimpleProperty(o, name);  
  91.                 BeanUtils.copyProperty(this, name, value);  
  92.             } catch (Exception e) {  
  93.                 log.error("copy prorperty error src=" + this.value, e);  
  94.             }  
  95.         }  
  96.     }  
  97.     /** 
  98.      * 
  99.      * 
  100.      * <p> 
  101.      * 将JsonField 标注了的基本属性组装成json字符串保存在value中 
  102.      * </p> 
  103.      * 
  104.      * @author <a href="mailto:qingxu@taobao.com" mce_href="mailto:qingxu@taobao.com">清虚</a> 
  105.      * @since 2.0 2009-10-19下午02:41:27 
  106.      * 
  107.      */  
  108.     @SuppressWarnings("unchecked")  
  109.     protected void encode() {  
  110.         JSONObject json = new JSONObject();  
  111.         Field[] fs = getClass().getDeclaredFields();  
  112.         for (Field f : fs) {  
  113.             if (f.isAnnotationPresent(JsonField.class)) {  
  114.                 String name = f.getName();  
  115.                 Object value = null;  
  116.                 try {  
  117.                     value=PropertyUtils.getSimpleProperty(this, name);  
  118.                     //value = f.get(this);  
  119.                 } catch (Exception e) {  
  120.                     log.error("get field value failed! fieldName=" + name, e);  
  121.                 }  
  122.                 if (value == null) {  
  123.                     continue;  
  124.                 }  
  125.                 Class type = f.getType();  
  126.                 if (Collection.class.isAssignableFrom(type)) {  
  127.                     Collection it = (Collection) value;  
  128.                     for (Object v : it) {  
  129.                         json.accumulate(name, v);  
  130.                     }  
  131.                 } else if (type.isArray()) {  
  132.                     json.put(name, JSONArray.fromObject(value));  
  133.                 } else {  
  134.                     json.put(name, value);  
  135.                 }  
  136.             }  
  137.         }  
  138.         this.value=json.toString();  
  139.         //setValue(json.toString());  
  140.     }  
  141.     /* 
  142.      * (non-Javadoc) 
  143.      * 
  144.      * @see java.lang.Object#toString() 
  145.      */  
  146.     @Override  
  147.     public String toString() {  
  148.         return ToStringBuilder.reflectionToString(this);  
  149.     }  

 

使用方式如下:

 

[java]  view plain copy print ?
  1. public class TrafficDO extends JsonDO {  
  2.     /** 
  3.      *序列号 
  4.      */  
  5.     private static final long serialVersionUID = -5673233152393642499L;  
  6.     @JsonField  
  7.     private String invoiceTitle;                            //发票抬头  
  8.     @JsonField  
  9.     private String fullName;                                //配送人姓名  
  10.     @JsonField  
  11.     private String mobileTel;                               //配送手机号码  
  12.     @JsonField  
  13.     private String province;                                //省  
  14.     @JsonField  
  15.     private String city;                                    //市  
  16.     @JsonField  
  17.     private String section;                                 //区  
  18.     @JsonField  
  19.     private String address;                                 //详细地址  
  20.     @JsonField  
  21.     private String post;                                    //邮编  
  22.     private int shipmentType;                               //配送方式  
  23.     public static final int BY_MAIL_TYPE = 0;               //挂号信邮寄方式  
  24.     public static final int BY_NOTNEED = -1;                //不需要行程单  
  25.   
  26.   
  27.         /** 
  28.      * @return the shipmentType 
  29.      */  
  30.     public int getShipmentType() {  
  31.         return shipmentType;  
  32.     }  
  33.     /** 
  34.      * @param shipmentType the shipmentType to set 
  35.      */  
  36.     public void setShipmentType(int shipmentType) {  
  37.         this.shipmentType = shipmentType;  
  38.     }  
  39.     /** 
  40.      * @return the fullName 
  41.      */  
  42.     public String getFullName() {  
  43.         return fullName;  
  44.     }  
  45.     /** 
  46.      * @param fullName the fullName to set 
  47.      */  
  48.     public void setFullName(String fullName) {  
  49.         this.fullName = fullName;  
  50.     }  
  51.     /** 
  52.      * @return the mobile 
  53.      */  
  54.     public String getMobileTel() {  
  55.         return mobileTel;  
  56.     }  
  57.     /** 
  58.      * @param mobile the mobile to set 
  59.      */  
  60.     public void setMobileTel(String mobile) {  
  61.         this.mobileTel = mobile;  
  62.     }  
  63.     /** 
  64.      * @return the province 
  65.      */  
  66.     public String getProvince() {  
  67.         return province;  
  68.     }  
  69.     /** 
  70.      * @param province the province to set 
  71.      */  
  72.     public void setProvince(String province) {  
  73.         this.province = province;  
  74.     }  
  75.     /** 
  76.      * @return the city 
  77.      */  
  78.     public String getCity() {  
  79.         return city;  
  80.     }  
  81.     /** 
  82.      * @param city the city to set 
  83.      */  
  84.     public void setCity(String city) {  
  85.         this.city = city;  
  86.     }  
  87.     /** 
  88.      * @return the section 
  89.      */  
  90.     public String getSection() {  
  91.         return section;  
  92.     }  
  93.     /** 
  94.      * @param section the section to set 
  95.      */  
  96.     public void setSection(String section) {  
  97.         this.section = section;  
  98.     }  
  99.     /** 
  100.      * @return the address 
  101.      */  
  102.     public String getAddress() {  
  103.         return address;  
  104.     }  
  105.     /** 
  106.      * @param address the address to set 
  107.      */  
  108.     public void setAddress(String address) {  
  109.         this.address = address;  
  110.     }  
  111.     /** 
  112.      * @return the post 
  113.      */  
  114.     public String getPost() {  
  115.         return post;  
  116.     }  
  117.     /** 
  118.      * @param post the post to set 
  119.      */  
  120.     public void setPost(String post) {  
  121.         this.post = post;  
  122.     }  
  123.     /** 
  124.      * 邮寄 
  125.      * 
  126.      * @return 
  127.      */  
  128.     public boolean isMail() {  
  129.         return this.shipmentType == BY_MAIL_TYPE;  
  130.     }  
  131.     /** 
  132.      * 不需要 
  133.      * 
  134.      * @author qingxu 
  135.      * @since 2007-10-25下午04:48:12 
  136.      * 
  137.      * @return 
  138.      */  
  139.     public boolean isNotNeed() {  
  140.         return this.shipmentType == BY_NOTNEED;  
  141.     }  
  142.     public String getInvoiceTitle() {  
  143.         return invoiceTitle;  
  144.     }  
  145.     public void setInvoiceTitle(String invoiceTitle) {  
  146.         this.invoiceTitle = invoiceTitle;  
  147.     }  
  148. }  

 

  @JsonField标注支持 基本类型和数组、collection类型域。

 

 

在从DB中load出traffic_description的值后

通过setValue()方法设置进去,那么所有的json域都会被填充好。同样的,如果填充了相应的json域,

在存储在数据库中时,可以调用getValue()得到字符串持久化到数据库中。

 

   通过getValue()得到的字符串形式如下:

 

[javascript]  view plain copy print ?
  1. {"section":"马龙县","fullName":"叮当","address":"vvvvvv","province":"云南省","invoiceTitle":"vvvvvv","mobileTel":"136**622627","post":"310014","city":"曲靖市"}  

 

    这种处理方式的好处是,可以方便的定义你自己要存储的内容,你所有做的仅仅是在新增一个field,然后在上面打上@JsonField标注即可。

    而它的缺点也是明显的,1、这种方式明显增加了存储内容的长度 2、由于存储的key是属性的名称,如果名称不匹配也会找不到对应的值。3、如果要对其中的内容进行条件检索,只有进行文本匹配,如果有这种需求,这种方式不推荐。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值