`
收藏列表
标题 标签 来源
Gson工具类
/*
 * Copyright 2010 Fuchun.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package my.tools;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
/**
 * 包含操作 {@code JSON} 数据的常用方法的工具类。
 * <p />
 * 该工具类使用的 {@code JSON} 转换引擎是 <a href="http://code.google.com/p/google-gson/" mce_href="http://code.google.com/p/google-gson/" target="_blank">
 * {@code Google Gson}</a>。 下面是工具类的使用案例:
 * 
 * <pre>
 * public class User { 
 *     @SerializedName("pwd")
 *     private String password; 
 *     @Expose
 *     @SerializedName("uname")
 *     private String username; 
 *     @Expose
 *     @Since(1.1)
 *     private String gender; 
 *     @Expose
 *     @Since(1.0)
 *     private String sex; 
 *      
 *     public User() {} 
 *     public User(String username, String password, String gender) { 
 *         // user constructor code... ... ... 
 *     } 
 *      
 *     public String getUsername() 
 *     ... ... ... 
 * }
 * List<User> userList = new LinkedList<User>(); 
 * User jack = new User("Jack", "123456", "Male"); 
 * User marry = new User("Marry", "888888", "Female"); 
 * userList.add(jack); 
 * userList.add(marry); 
 * Type targetType = new TypeToken<List<User>>(){}.getType(); 
 * String sUserList1 = JSONUtils.toJson(userList, targetType); 
 * sUserList1 ----> [{"uname":"jack","gender":"Male","sex":"Male"},{"uname":"marry","gender":"Female","sex":"Female"}] 
 * String sUserList2 = JSONUtils.toJson(userList, targetType, false); 
 * sUserList2 ----> [{"uname":"jack","pwd":"123456","gender":"Male","sex":"Male"},{"uname":"marry","pwd":"888888","gender":"Female","sex":"Female"}] 
 * String sUserList3 = JSONUtils.toJson(userList, targetType, 1.0d, true); 
 * sUserList3 ----> [{"uname":"jack","sex":"Male"},{"uname":"marry","sex":"Female"}]
 * </pre>
 * 
 * @author Fuchun
 * @since ay-commons-lang 1.0
 * @version 1.1.0
 */
public class JSONUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(JSONUtils.class);
    /** 空的 {@code JSON} 数据 - <code>"{}"</code>。 */
    public static final String EMPTY_JSON = "{}";
    /** 空的 {@code JSON} 数组(集合)数据 - {@code "[]"}。 */
    public static final String EMPTY_JSON_ARRAY = "[]";
    /** 默认的 {@code JSON} 日期/时间字段的格式化模式。 */
    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss SSS";
    /** {@code Google Gson} 的 <code>@Since</code> 注解常用的版本号常量 - {@code 1.0}。 */
    public static final double SINCE_VERSION_10 = 1.0d;
    /** {@code Google Gson} 的 <code>@Since</code> 注解常用的版本号常量 - {@code 1.1}。 */
    public static final double SINCE_VERSION_11 = 1.1d;
    /** {@code Google Gson} 的 <code>@Since</code> 注解常用的版本号常量 - {@code 1.2}。 */
    public static final double SINCE_VERSION_12 = 1.2d;
    /** {@code Google Gson} 的 <code>@Until</code> 注解常用的版本号常量 - {@code 1.0}。 */
    public static final double UNTIL_VERSION_10 = SINCE_VERSION_10;
    /** {@code Google Gson} 的 <code>@Until</code> 注解常用的版本号常量 - {@code 1.1}。 */
    public static final double UNTIL_VERSION_11 = SINCE_VERSION_11;
    /** {@code Google Gson} 的 <code>@Until</code> 注解常用的版本号常量 - {@code 1.2}。 */
    public static final double UNTIL_VERSION_12 = SINCE_VERSION_12;
    /**
     * <p>
     * <code>JSONUtils</code> instances should NOT be constructed in standard programming. Instead,
     * the class should be used as <code>JSONUtils.fromJson("foo");</code>.
     * </p>
     * <p>
     * This constructor is public to permit tools that require a JavaBean instance to operate.
     * </p>
     */
    public JSONUtils() {
        super();
    }
    /**
     * 将给定的目标对象根据指定的条件参数转换成 {@code JSON} 格式的字符串。
     * <p />
     * <strong>该方法转换发生错误时,不会抛出任何异常。若发生错误时,曾通对象返回 <code>"{}"</code>; 集合或数组对象返回 <code>"[]"</code>
     * </strong>
     * 
     * @param target 目标对象。
     * @param targetType 目标对象的类型。
     * @param isSerializeNulls 是否序列化 {@code null} 值字段。
     * @param version 字段的版本号注解。
     * @param datePattern 日期字段的格式化模式。
     * @param excludesFieldsWithoutExpose 是否排除未标注 {@literal @Expose} 注解的字段。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, Type targetType, boolean isSerializeNulls, Double version,
            String datePattern, boolean excludesFieldsWithoutExpose) {
        if (target == null) return EMPTY_JSON;
        GsonBuilder builder = new GsonBuilder();
        if (isSerializeNulls) builder.serializeNulls();
        if (version != null) builder.setVersion(version.doubleValue());
        if (StringUtils.isBlank(datePattern)) datePattern = DEFAULT_DATE_PATTERN;
        builder.setDateFormat(datePattern);
        if (excludesFieldsWithoutExpose) builder.excludeFieldsWithoutExposeAnnotation();
        return toJson(target, targetType, builder);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法只用来转换普通的 {@code JavaBean} 对象。</strong>
     * <ul>
     * <li>该方法只会转换标有 {@literal @Expose} 注解的字段;</li>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法会转换所有未标注或已标注 {@literal @Since} 的字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target) {
        return toJson(target, null, false, null, null, true);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法只用来转换普通的 {@code JavaBean} 对象。</strong>
     * <ul>
     * <li>该方法只会转换标有 {@literal @Expose} 注解的字段;</li>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法会转换所有未标注或已标注 {@literal @Since} 的字段;</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param datePattern 日期字段的格式化模式。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, String datePattern) {
        return toJson(target, null, false, null, datePattern, true);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法只用来转换普通的 {@code JavaBean} 对象。</strong>
     * <ul>
     * <li>该方法只会转换标有 {@literal @Expose} 注解的字段;</li>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param version 字段的版本号注解({@literal @Since})。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, Double version) {
        return toJson(target, null, false, version, null, true);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法只用来转换普通的 {@code JavaBean} 对象。</strong>
     * <ul>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法会转换所有未标注或已标注 {@literal @Since} 的字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param excludesFieldsWithoutExpose 是否排除未标注 {@literal @Expose} 注解的字段。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, boolean excludesFieldsWithoutExpose) {
        return toJson(target, null, false, null, null, excludesFieldsWithoutExpose);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法只用来转换普通的 {@code JavaBean} 对象。</strong>
     * <ul>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param version 字段的版本号注解({@literal @Since})。
     * @param excludesFieldsWithoutExpose 是否排除未标注 {@literal @Expose} 注解的字段。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, Double version, boolean excludesFieldsWithoutExpose) {
        return toJson(target, null, false, version, null, excludesFieldsWithoutExpose);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法通常用来转换使用泛型的对象。</strong>
     * <ul>
     * <li>该方法只会转换标有 {@literal @Expose} 注解的字段;</li>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法会转换所有未标注或已标注 {@literal @Since} 的字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param targetType 目标对象的类型。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, Type targetType) {
        return toJson(target, targetType, false, null, null, true);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法通常用来转换使用泛型的对象。</strong>
     * <ul>
     * <li>该方法只会转换标有 {@literal @Expose} 注解的字段;</li>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param targetType 目标对象的类型。
     * @param version 字段的版本号注解({@literal @Since})。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, Type targetType, Double version) {
        return toJson(target, targetType, false, version, null, true);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法通常用来转换使用泛型的对象。</strong>
     * <ul>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法会转换所有未标注或已标注 {@literal @Since} 的字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param targetType 目标对象的类型。
     * @param excludesFieldsWithoutExpose 是否排除未标注 {@literal @Expose} 注解的字段。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, Type targetType, boolean excludesFieldsWithoutExpose) {
        return toJson(target, targetType, false, null, null, excludesFieldsWithoutExpose);
    }
    /**
     * 将给定的目标对象转换成 {@code JSON} 格式的字符串。<strong>此方法通常用来转换使用泛型的对象。</strong>
     * <ul>
     * <li>该方法不会转换 {@code null} 值字段;</li>
     * <li>该方法转换时使用默认的 日期/时间 格式化模式 - {@code yyyy-MM-dd HH:mm:ss SSS};</li>
     * </ul>
     * 
     * @param target 要转换成 {@code JSON} 的目标对象。
     * @param targetType 目标对象的类型。
     * @param version 字段的版本号注解({@literal @Since})。
     * @param excludesFieldsWithoutExpose 是否排除未标注 {@literal @Expose} 注解的字段。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.0
     */
    public static String toJson(Object target, Type targetType, Double version, boolean excludesFieldsWithoutExpose) {
        return toJson(target, targetType, false, version, null, excludesFieldsWithoutExpose);
    }
    /**
     * 将给定的 {@code JSON} 字符串转换成指定的类型对象。
     * 
     * @param <T> 要转换的目标类型。
     * @param json 给定的 {@code JSON} 字符串。
     * @param token {@code com.google.gson.reflect.TypeToken} 的类型指示类对象。
     * @param datePattern 日期格式模式。
     * @return 给定的 {@code JSON} 字符串表示的指定的类型对象。
     * @since 1.0
     */
    public static <T> T fromJson(String json, TypeToken<T> token, String datePattern) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        GsonBuilder builder = new GsonBuilder();
        if (StringUtils.isBlank(datePattern)) {
            datePattern = DEFAULT_DATE_PATTERN;
        }
        Gson gson = builder.create();
        try {
            return gson.fromJson(json, token.getType());
        } catch (Exception ex) {
            LOGGER.error(json + " 无法转换为 " + token.getRawType().getName() + " 对象!", ex);
            return null;
        }
    }
    /**
     * 将给定的 {@code JSON} 字符串转换成指定的类型对象。
     * 
     * @param <T> 要转换的目标类型。
     * @param json 给定的 {@code JSON} 字符串。
     * @param token {@code com.google.gson.reflect.TypeToken} 的类型指示类对象。
     * @return 给定的 {@code JSON} 字符串表示的指定的类型对象。
     * @since 1.0
     */
    public static <T> T fromJson(String json, TypeToken<T> token) {
        return fromJson(json, token, null);
    }
    /**
     * 将给定的 {@code JSON} 字符串转换成指定的类型对象。<strong>此方法通常用来转换普通的 {@code JavaBean} 对象。</strong>
     * 
     * @param <T> 要转换的目标类型。
     * @param json 给定的 {@code JSON} 字符串。
     * @param clazz 要转换的目标类。
     * @param datePattern 日期格式模式。
     * @return 给定的 {@code JSON} 字符串表示的指定的类型对象。
     * @since 1.0
     */
    public static <T> T fromJson(String json, Class<T> clazz, String datePattern) {
        if (StringUtils.isBlank(json)) {
            return null;
        }
        GsonBuilder builder = new GsonBuilder();
        if (StringUtils.isBlank(datePattern)) {
            datePattern = DEFAULT_DATE_PATTERN;
        }
        Gson gson = builder.create();
        try {
            return gson.fromJson(json, clazz);
        } catch (Exception ex) {
            LOGGER.error(json + " 无法转换为 " + clazz.getName() + " 对象!", ex);
            return null;
        }
    }
    /**
     * 将给定的 {@code JSON} 字符串转换成指定的类型对象。<strong>此方法通常用来转换普通的 {@code JavaBean} 对象。</strong>
     * 
     * @param <T> 要转换的目标类型。
     * @param json 给定的 {@code JSON} 字符串。
     * @param clazz 要转换的目标类。
     * @return 给定的 {@code JSON} 字符串表示的指定的类型对象。
     * @since 1.0
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        return fromJson(json, clazz, null);
    }
    /**
     * 将给定的目标对象根据{@code GsonBuilder} 所指定的条件参数转换成 {@code JSON} 格式的字符串。
     * <p />
     * 该方法转换发生错误时,不会抛出任何异常。若发生错误时,{@code JavaBean} 对象返回 <code>"{}"</code>; 集合或数组对象返回
     * <code>"[]"</code>。 其本基本类型,返回相应的基本值。
     * 
     * @param target 目标对象。
     * @param targetType 目标对象的类型。
     * @param builder 可定制的{@code Gson} 构建器。
     * @return 目标对象的 {@code JSON} 格式的字符串。
     * @since 1.1
     */
    public static String toJson(Object target, Type targetType, GsonBuilder builder) {
        if (target == null) return EMPTY_JSON;
        Gson gson = null;
        if (builder == null) {
            gson = new Gson();
        } else {
            gson = builder.create();
        }
        String result = EMPTY_JSON;
        try {
            if (targetType == null) {
                result = gson.toJson(target);
            } else {
                result = gson.toJson(target, targetType);
            }
        } catch (Exception ex) {
            LOGGER.warn("目标对象 " + target.getClass().getName() + " 转换 JSON 字符串时,发生异常!", ex);
            if (target instanceof Collection<?> || target instanceof Iterator<?> || target instanceof Enumeration<?>
                    || target.getClass().isArray()) {
                result = EMPTY_JSON_ARRAY;
            }
        }
        return result;
    }
}
gson应用例子
1)普通JavaBean类/带日期属性的JavaBean类:JavaBean.java/DateBean.java
 
2)日期序列/反序列工具类:DateSerializerUtils.java、DateDeserializerUtils.java
 
3)测试类GsonTester.java
 
具体代码:
 
1)JavaBean类/DateBean类
 
     JavaBean属性:String id、String name、int age、String addr;
 
     DateBean属性:String id、String name、int age、java.util.Date date;
 
2)
 
DateSerializerUtils.java
 
package com.lupeng.javase.json.util;
 
  
 
import java.lang.reflect.Type;
 
import java.util.Date;
 
import com.google.gson.JsonElement;
 
import com.google.gson.JsonPrimitive;
 
import com.google.gson.JsonSerializationContext;
 
import com.google.gson.JsonSerializer;
 
  
 
/**
 
 * 日期解序列实用工具类
 
 * @author Lupeng
 
 * @date   2011-08-06
 
 */
 
public class DateSerializerUtils implements JsonSerializer<java.util.Date>{
 
    @Override
 
    public JsonElement serialize(Date date, Type type,
 
           JsonSerializationContext content) {
 
       return new JsonPrimitive(date.getTime());
 
    }
 
  
 
}
 
DateDeserializerUtils.java
 
package com.lupeng.javase.json.util;
 
  
 
import java.lang.reflect.Type;
 
import com.google.gson.JsonDeserializationContext;
 
import com.google.gson.JsonDeserializer;
 
import com.google.gson.JsonElement;
 
import com.google.gson.JsonParseException;
 
/**
 
 * 日期序列化实用工具类
 
 * @author Lupeng
 
 * @date   2011-08-06
 
 */
 
public class DateDeserializerUtils implements JsonDeserializer<java.util.Date>{
 
    @Override
 
    public java.util.Date deserialize(JsonElement json, Type type,
 
           JsonDeserializationContext context) throws JsonParseException {
 
       return new java.util.Date(json.getAsJsonPrimitive().getAsLong());
 
    }
 
  
 
}
 
  
 
3)测试类GsonTester.java
 
package com.lupeng.javase.apps.json;
 
  
 
import java.text.DateFormat;
 
import java.util.ArrayList;
 
import java.util.Date;
 
import java.util.HashMap;
 
import java.util.List;
 
import java.util.Map;
 
  
 
import org.junit.Before;
 
import org.junit.Test;
 
  
 
import com.google.gson.Gson;
 
import com.google.gson.GsonBuilder;
 
import com.lupeng.javase.json.bean.DateBean;
 
import com.lupeng.javase.json.bean.JavaBean;
 
import com.lupeng.javase.json.util.DateDeserializerUtils;
 
import com.lupeng.javase.json.util.DateSerializerUtils;
 
  
 
/**
 
 * Google Gson解析Json数据实例
 
 *
 
 * 1.Bean、Json转换          testBeanJson()
 
 * 2.List -> Json转换     testList2Json()
 
 * 3.泛型List、Json相互转换 testGenericList2Json()
 
 * 4.Map -> Json转换         testMap2Json()
 
 * 5.泛型Map、Json相互转换 testGenericMap2Json()
 
 * 6.带日期属性Bean、Json转换  testDateBeanJson()
 
 * 7.带日期属性泛型List、Json转换
 
 *                           testDateGenericListJson()
 
 *
 
 * @author Lupeng
 
 * @create 2011-08-05
 
 * @modify 2011-08-06
 
 */
 
@SuppressWarnings("unchecked")
 
public class GsonTester {
 
    private Gson gson = null;
 
    private GsonBuilder gsonBuilder = null;
 
    
 
    @Before
 
    public void setUp() {
 
       gson = new Gson();
 
       gsonBuilder = new GsonBuilder();
 
    }
 
    /**
 
     * JavaBean、Json相互转换
 
     */
 
    @Test
 
    public void testBeanJson() {
 
       JavaBean bean = new JavaBean("1001", "scott", 20, "TL");
 
       
 
       // Bean -> Json
 
       String json = gson.toJson(bean);
 
       System.out.println(json);
 
       
 
       // Json -> Bean
 
       bean = gson.fromJson(json, JavaBean.class);
 
       System.out.println(bean);
 
    }
 
    
 
    /**
 
     * List转换成Json字符串
 
     */
 
    @Test
 
    public void testList2Json() {
 
       // List
 
       List list = new ArrayList();
 
       for(int i = 0; i < 5; i++) {
 
           list.add("element" + i);
 
       }
 
       System.out.println(list);
 
       
 
       // List -> Json
 
       String json = gson.toJson(list);
 
       System.out.println(json);
 
    }
 
    
 
    /**
 
     * 泛型List、Json相互转换
 
     */
 
    @Test
 
    public void testGenericListJson() {
 
       // 泛型List
 
       List<JavaBean> list = new ArrayList<JavaBean>();
 
       for(int i = 0; i < 3; i++) {
 
           JavaBean user = new JavaBean("100" + i, "name" + i, 20 + i, "BJ" + i);
 
           list.add(user);
 
       }
 
       System.out.println(list);
 
       
 
       // 泛型List -> Json
 
       java.lang.reflect.Type type =
 
           new com.google.gson.reflect.TypeToken<List<JavaBean>>(){}.getType();
 
       String json = gson.toJson(list, type);
 
       System.out.println(json);  
 
       
 
       // Json -> 泛型List
 
       List<JavaBean> users = gson.fromJson(json.toString(), type);
 
       System.out.println(users);
 
    }
 
    
 
    /**
 
     * Map转换成Json字符串
 
     */
 
    @Test
 
    public void testMap2Json() {
 
       // Map数据
 
       Map map = new HashMap();
 
       map.put("id", "1001");
 
       map.put("name", "scott");
 
       map.put("age", 20);
 
       map.put("addr", "BJ");
 
       System.out.println(map);
 
       
 
       // Map -> Json
 
       String json = gson.toJson(map);
 
       System.out.println(json);
 
    }
 
    
 
    /**
 
     * 泛型Map、Json相互转换
 
     */
 
    @Test
 
    public void testGenericMapJson() {
 
       // 泛型Map数据
 
       Map<String, JavaBean> map = new HashMap<String, JavaBean>();
 
       for(int i = 0; i < 5; i++) {
 
           JavaBean user = new JavaBean("100" + i, "name" + i, 20 + i, "LN" + i);
 
           map.put("100" + i, user);
 
       }
 
       System.out.println(map);
 
       
 
       // 泛型Map -> Json
 
       java.lang.reflect.Type type =
 
           new com.google.gson.reflect.TypeToken<Map<String, JavaBean>>(){}.getType();
 
       String json = gson.toJson(map, type);
 
       System.out.println(json);  
 
       
 
       // Json -> Map
 
       Map<String, JavaBean> users = gson.fromJson(json.toString(), type);
 
       System.out.println(users);
 
       
 
    }
 
    
 
    /**
 
     * 带日期类型Bean、Json相互转换
 
     */
 
    @Test
 
    public void testDateBeanJson() {
 
       // 日期Bean数据
 
       DateBean bean = new DateBean("1001", "scott", 20, new Date());
 
       
 
       // Bean(带日期属性) -> Json
 
       gson = gsonBuilder.registerTypeAdapter(java.util.Date.class,
 
              new DateSerializerUtils()).setDateFormat(DateFormat.LONG).create();
 
       String json = gson.toJson(bean);
 
       System.out.println(json);
 
       
 
       // Json -> Bean(带日期类型属性)
 
       gson = gsonBuilder.registerTypeAdapter(java.util.Date.class,
 
              new DateDeserializerUtils()).setDateFormat(DateFormat.LONG).create();
 
       java.lang.reflect.Type type =
 
           new com.google.gson.reflect.TypeToken<DateBean>(){}.getType();
 
       DateBean b = gson.fromJson(json, type);
 
       System.out.println(b);
 
    }
 
    /**
 
     * 泛型日期List、Json相互转换
 
     */
 
    @Test
 
    public void testDateGenericListJson() {
 
       // 泛型日期List
 
       List<DateBean> list = new ArrayList<DateBean>();
 
       for(int i = 0; i < 3; i++) {
 
           DateBean user = new DateBean("100" + i, "name" + i, 20 + i, new Date());
 
           list.add(user);
 
       }
 
       System.out.println(list);
 
       
 
       // 泛型日期List -> Json
 
       gson = gsonBuilder.registerTypeAdapter(java.util.Date.class,
 
              new DateSerializerUtils()).setDateFormat(DateFormat.LONG).create();
 
       java.lang.reflect.Type type =
 
           new com.google.gson.reflect.TypeToken<List<DateBean>>(){}.getType();
 
       String json = gson.toJson(list, type);
 
       System.out.println(json);  
 
       
 
       // Json -> 泛型日期List
 
       gson = gsonBuilder.registerTypeAdapter(java.util.Date.class,
 
              new DateDeserializerUtils()).setDateFormat(DateFormat.LONG).create();
 
       List<DateBean> users = gson.fromJson(json.toString(), type);
 
       System.out.println(users);
 
    }
 
}
gson对list反序列化处理
Type listType = new TypeToken<List<T>>() {}.getType();
gson.fromJson(json, listType);

Gson g = new Gson();
String[] sss= {"1","22","sss"};
String jsonString = g.toJson(sss);
List<String> groups = g.fromJson(jsonString, new TypeToken<List<String>>() {}.getType());
java和android平台加密处理类
package com.lectek.lereader.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Encoder;

import com.lectek.lereader.utils.security.Base64;

/**
 * 加密工具类
 * 
 * @author limj
 * 
 */
public class EncryptUtils {
	// 向量
	private final static String iv = "01234567";
	// 加解密统一使用的编码方式
	private final static String encoding = "utf-8";

	/**
	 * AES加密输入流
	 * 
	 * @param in
	 *            输入流
	 * @param password
	 *            加密密码
	 * @return
	 */
	public static byte[] encryptByAES(InputStream in, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			CipherInputStream cin = new CipherInputStream(in, cipher);
			byte[] result = inputStreamToByte(cin);// cipher.doFinal(byteContent);
			return result; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * AES加密字节数组
	 * 
	 * @param byteContent
	 *            字节数组
	 * @param password
	 *            加密密码
	 * @return
	 */
	public static byte[] encryptByAES(byte[] byteContent, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			// byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * AES加密字符串
	 * 
	 * @param content
	 *            加密字符串
	 * @param password
	 *            加密密码
	 * @return
	 */
	public static byte[] encryptByAES(String content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			return result; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Base64(AES加密字符串)
	 * 
	 * @param content
	 *            加密字符串
	 * @param password
	 *            加密密码
	 * @return
	 */
	public static String encryptBase64AES(String content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			byte[] byteContent = content.getBytes("utf-8");
			cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(byteContent);
			BASE64Encoder base64en = new BASE64Encoder();
			return base64en.encode(result);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解密
	 * 
	 * @param content
	 *            待解密内容
	 * @param password
	 *            解密密钥
	 * @return
	 */
	public static byte[] decryptByAES(byte[] content, String password) {
		try {
			KeyGenerator kgen = KeyGenerator.getInstance("AES");
			kgen.init(128, new SecureRandom(password.getBytes()));
			SecretKey secretKey = kgen.generateKey();
			byte[] enCodeFormat = secretKey.getEncoded();
			SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
			Cipher cipher = Cipher.getInstance("AES");// 创建密码器
			cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
			byte[] result = cipher.doFinal(content);
			return result; // 加密
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 对字符串加密(32位)
	 * 
	 * @param str
	 * @return
	 */
	public static final String encodeByMd5(String str) {
		if (str == null) {
			return "";
		} else {
			String newstr = "";
			MessageDigest md5;
			try {
				md5 = MessageDigest.getInstance("MD5");
				md5.update(str.getBytes("utf-8"));
				byte resultData[] = md5.digest();
				newstr = convertToHexString(resultData);
				// BASE64Encoder base64en = new BASE64Encoder();
				// 加密后的字符串
				// newstr = base64en.encode(md5.digest(str.getBytes("utf-8")));
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return newstr;
		}
	}

	/**
	 * 对字符串加密(32位)
	 * 
	 * @param str
	 * @return
	 */
	public static final String encryptBase64MD5(String str) {
		if (str == null) {
			return "";
		} else {
			String newstr = "";
			MessageDigest md5;
			try {
				md5 = MessageDigest.getInstance("MD5");
				BASE64Encoder base64en = new BASE64Encoder();
				// 加密后的字符串
				newstr = base64en.encode(md5.digest(str.getBytes("utf-8")));
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (UnsupportedEncodingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return newstr;
		}
	}

	/**
	 * 3DES加密后Base64
	 * 
	 * @param source
	 * @param key
	 * @return
	 */
	public static String encryptBase643DES(String source, String key) {
		try {
			Key deskey = null;
			DESedeKeySpec spec = new DESedeKeySpec(key.getBytes());
			SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
			deskey = keyfactory.generateSecret(spec);

			Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
			IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
			cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
			byte[] encryptData = cipher.doFinal(source.getBytes(encoding));
			return Base64.encode(encryptData);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Base643DES解密
	 * 
	 * @param source
	 * @param key
	 * @return
	 */
	public static String decryptBase643DES(String source, String key) {
		try {
			Key deskey = null;
			DESedeKeySpec spec = new DESedeKeySpec(key.getBytes());
			SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
			deskey = keyfactory.generateSecret(spec);
			Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
			IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
			cipher.init(Cipher.DECRYPT_MODE, deskey, ips);

			byte[] decryptData = cipher.doFinal(Base64.decode(source));

			return new String(decryptData, encoding);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * byte[]转String
	 * 
	 * @param data
	 * @return
	 */
	public static String convertToHexString(byte data[]) {
		StringBuffer strBuffer = new StringBuffer();
		for (int i = 0; i < data.length; i++) {
			if ((0xff & data[i]) < 0x10) {
				strBuffer.append("0" + Integer.toHexString((0xFF & data[i])));
			} else {
				strBuffer.append(Integer.toHexString(0xFF & data[i]));
			}
		}
		return strBuffer.toString();
	}

	/**
	 * 流转byte[]
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static byte[] inputStreamToByte(InputStream is) throws IOException {
		ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
		int ch;
		while ((ch = is.read()) != -1) {
			bytestream.write(ch);
		}
		byte data[] = bytestream.toByteArray();
		bytestream.close();
		return data;
	}

	/**
	 * 对byte数组base64加密
	 * 
	 * @param b
	 * @return
	 */
	public static String base64Encode(byte b[]) {
		try {
			return (new BASE64Encoder()).encode(b);
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) throws Exception {
		// md5
		/*
		 * String md5 = EncryptUtils.encodeByMd5("123456");
		 * System.out.println(md5);// e10adc3949ba59abbe56e057f20f883e // 3DES
		 * String encryByDES =
		 * EncryptUtils.encryptBase643DES("1.010000000011000000001",
		 * "lereaderV1.0secretkey123");// 24 System.out.println("digest:" +
		 * encryByDES);// digest:4kUGCk1X8zAZsoKe5oSvUfiaDcC3gK6H String
		 * decryByDES = EncryptUtils.decryptBase643DES(encryByDES,
		 * "lereaderV1.0secretkey123"); System.out.println(decryByDES); // REK
		 * String rek = EncryptUtils.encodeByMd5("1.010000000011000000001" +
		 * "lereaderV1.0secretkey123"); System.out.println("rek:" + rek);//
		 * rek:263edb7c516354a7b756deb74eb37d30 // secretKey String byteArr =
		 * EncryptUtils.encryptBase64AES("b8403b65f815",
		 * "263edb7c516354a7b756deb74eb37d30"); System.out.println("byteArr:" +
		 * byteArr);// ceiUxvcjxJI2IhI3Ez2XVQ== String secretKey = new
		 * String(EncryptUtils.decryptByAES((new
		 * BASE64Decoder()).decodeBuffer(byteArr),
		 * "263edb7c516354a7b756deb74eb37d30"), "utf-8");
		 * System.out.println("secretKey:" + secretKey);
		 */// b8403b65f815
		String key = "lereaderV1.0secretkey123";
		String encryString = EncryptUtils.encryptBase643DES("hello", key);
		System.out.println("encry== " + encryString);
		System.out.println(EncryptUtils.decryptBase643DES(encryString, key));
		/*
		 * String fileName = "D:/social/test1.epub"; InputStream in = new
		 * FileInputStream(fileName); byte[] byteContent =
		 * FileUtils.InputStreamToByte(in); byte[] decryptContent =
		 * EncryptUtils.decryptByAES(byteContent, "b8403b65f815");
		 * FileUtils.getFile(decryptContent, "D:/social", "test11.epub");
		 */
	}

}

/*
 * Copyright (C) 2010 The MobileSecurePay Project
 * All right reserved.
 * author: shiqun.shi@alipay.com
 */

package com.lectek.lereader.utils.security;

public final class Base64 {

    static private final int     BASELENGTH           = 128;
    static private final int     LOOKUPLENGTH         = 64;
    static private final int     TWENTYFOURBITGROUP   = 24;
    static private final int     EIGHTBIT             = 8;
    static private final int     SIXTEENBIT           = 16;
    static private final int     FOURBYTE             = 4;
    static private final int     SIGN                 = -128;
    static private final char    PAD                  = '=';
    static private final boolean fDebug               = false;
    static final private byte[]  base64Alphabet       = new byte[BASELENGTH];
    static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH];

    static {
        for (int i = 0; i < BASELENGTH; ++i) {
            base64Alphabet[i] = -1;
        }
        for (int i = 'Z'; i >= 'A'; i--) {
            base64Alphabet[i] = (byte) (i - 'A');
        }
        for (int i = 'z'; i >= 'a'; i--) {
            base64Alphabet[i] = (byte) (i - 'a' + 26);
        }

        for (int i = '9'; i >= '0'; i--) {
            base64Alphabet[i] = (byte) (i - '0' + 52);
        }

        base64Alphabet['+'] = 62;
        base64Alphabet['/'] = 63;

        for (int i = 0; i <= 25; i++) {
            lookUpBase64Alphabet[i] = (char) ('A' + i);
        }

        for (int i = 26, j = 0; i <= 51; i++, j++) {
            lookUpBase64Alphabet[i] = (char) ('a' + j);
        }

        for (int i = 52, j = 0; i <= 61; i++, j++) {
            lookUpBase64Alphabet[i] = (char) ('0' + j);
        }
        lookUpBase64Alphabet[62] = (char) '+';
        lookUpBase64Alphabet[63] = (char) '/';

    }

    private static boolean isWhiteSpace(char octect) {
        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
    }

    private static boolean isPad(char octect) {
        return (octect == PAD);
    }

    private static boolean isData(char octect) {
        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
    }

    /**
     * Encodes hex octects into Base64
     *
     * @param binaryData Array containing binaryData
     * @return Encoded Base64 array
     */
    public static String encode(byte[] binaryData) {

        if (binaryData == null) {
            return null;
        }

        int lengthDataBits = binaryData.length * EIGHTBIT;
        if (lengthDataBits == 0) {
            return "";
        }

        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
        char encodedData[] = null;

        encodedData = new char[numberQuartet * 4];

        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;

        int encodedIndex = 0;
        int dataIndex = 0;
        if (fDebug) {
            System.out.println("number of triplets = " + numberTriplets);
        }

        for (int i = 0; i < numberTriplets; i++) {
            b1 = binaryData[dataIndex++];
            b2 = binaryData[dataIndex++];
            b3 = binaryData[dataIndex++];

            if (fDebug) {
                System.out.println("b1= " + b1 + ", b2= " + b2 + ", b3= " + b3);
            }

            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);

            if (fDebug) {
                System.out.println("val2 = " + val2);
                System.out.println("k4   = " + (k << 4));
                System.out.println("vak  = " + (val2 | (k << 4)));
            }

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
        }

        // form integral number of 6-bit groups
        if (fewerThan24bits == EIGHTBIT) {
            b1 = binaryData[dataIndex];
            k = (byte) (b1 & 0x03);
            if (fDebug) {
                System.out.println("b1=" + b1);
                System.out.println("b1<<2 = " + (b1 >> 2));
            }
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
            encodedData[encodedIndex++] = PAD;
            encodedData[encodedIndex++] = PAD;
        } else if (fewerThan24bits == SIXTEENBIT) {
            b1 = binaryData[dataIndex];
            b2 = binaryData[dataIndex + 1];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
            encodedData[encodedIndex++] = PAD;
        }

        return new String(encodedData);
    }

    /**
     * Decodes Base64 data into octects
     *
     * @param encoded string containing Base64 data
     * @return Array containind decoded data.
     */
    public static byte[] decode(String encoded) {

        if (encoded == null) {
            return null;
        }

        char[] base64Data = encoded.toCharArray();
        // remove white spaces
        int len = removeWhiteSpace(base64Data);

        if (len % FOURBYTE != 0) {
            return null;//should be divisible by four
        }

        int numberQuadruple = (len / FOURBYTE);

        if (numberQuadruple == 0) {
            return new byte[0];
        }

        byte decodedData[] = null;
        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;

        int i = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        decodedData = new byte[(numberQuadruple) * 3];

        for (; i < numberQuadruple - 1; i++) {

            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
                || !isData((d3 = base64Data[dataIndex++]))
                || !isData((d4 = base64Data[dataIndex++]))) {
                return null;
            }//if found "no data" just return null

            b1 = base64Alphabet[d1];
            b2 = base64Alphabet[d2];
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];

            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }

        if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) {
            return null;//if found "no data" just return null
        }

        b1 = base64Alphabet[d1];
        b2 = base64Alphabet[d2];

        d3 = base64Data[dataIndex++];
        d4 = base64Data[dataIndex++];
        if (!isData((d3)) || !isData((d4))) {//Check if they are PAD characters
            if (isPad(d3) && isPad(d4)) {
                if ((b2 & 0xf) != 0)//last 4 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 1];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                return tmp;
            } else if (!isPad(d3) && isPad(d4)) {
                b3 = base64Alphabet[d3];
                if ((b3 & 0x3) != 0)//last 2 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 2];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                return tmp;
            } else {
                return null;
            }
        } else { //No PAD e.g 3cQl
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);

        }

        return decodedData;
    }

    /**
     * remove WhiteSpace from MIME containing encoded Base64 data.
     *
     * @param data  the byte array of base64 data (with WS)
     * @return      the new length
     */
    private static int removeWhiteSpace(char[] data) {
        if (data == null) {
            return 0;
        }

        // count characters that's not whitespace
        int newSize = 0;
        int len = data.length;
        for (int i = 0; i < len; i++) {
            if (!isWhiteSpace(data[i])) {
                data[newSize++] = data[i];
            }
        }
        return newSize;
    }
}


Android、iPhone和Java三个平台一致的加密工具
 移动开发中遇到的最让人纠结的要属Java、Android和iPhone三个平台加解密不一致的问题。因为手机端后台通常是用JAVA开发的Web Service,Android和iPhone客户端调用同样的Web Service接口,为了数据安全考虑,要对数据进行加密。头疼的问题就来了,很难编写出一套加密程序,在3个平台间加解密的结果一致,总不能为Android和iPhone两个客户端各写一套Web Service接口吧?我相信还会有很多朋友为此困惑,在此分享一套3DES加密程序,能够实现Java、Android和iPhone三个平台加解密一致。 

        首先是JAVA端的加密工具类,它同样适用于Android端,无需任何修改,即可保证Java与Android端的加解密一致,并且中文不会乱码。 
Java代码  
package org.liuyq.des3;  
  
import java.security.Key;  
  
import javax.crypto.Cipher;  
import javax.crypto.SecretKeyFactory;  
import javax.crypto.spec.DESedeKeySpec;  
import javax.crypto.spec.IvParameterSpec;  
  
/** 
 * 3DES加密工具类 
 */  
public class Des3 {  
    // 密钥  
    private final static String secretKey = "liuyunqiang@lx100$#365#$";  
    // 向量  
    private final static String iv = "01234567";  
    // 加解密统一使用的编码方式  
    private final static String encoding = "utf-8";  
  
    /** 
     * 3DES加密 
     *  
     * @param plainText 普通文本 
     * @return 
     * @throws Exception  
     */  
    public static String encode(String plainText) throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
  
        Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");  
        IvParameterSpec ips = new IvParameterSpec(iv.getBytes());  
        cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);  
        byte[] encryptData = cipher.doFinal(plainText.getBytes(encoding));  
        return Base64.encode(encryptData);  
    }  
  
    /** 
     * 3DES解密 
     *  
     * @param encryptText 加密文本 
     * @return 
     * @throws Exception 
     */  
    public static String decode(String encryptText) throws Exception {  
        Key deskey = null;  
        DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());  
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");  
        deskey = keyfactory.generateSecret(spec);  
        Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");  
        IvParameterSpec ips = new IvParameterSpec(iv.getBytes());  
        cipher.init(Cipher.DECRYPT_MODE, deskey, ips);  
  
        byte[] decryptData = cipher.doFinal(Base64.decode(encryptText));  
  
        return new String(decryptData, encoding);  
    }  
}  


上面的加密工具类会使用到Base64这个类,该类的源代码如下: 
Java代码  
import java.io.ByteArrayOutputStream;  
import java.io.IOException;  
import java.io.OutputStream;  
  
/** 
 * Base64编码工具类 
 */  
public class Base64 {  
    private static final char[] legalChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();  
  
    public static String encode(byte[] data) {  
        int start = 0;  
        int len = data.length;  
        StringBuffer buf = new StringBuffer(data.length * 3 / 2);  
  
        int end = len - 3;  
        int i = start;  
        int n = 0;  
  
        while (i <= end) {  
            int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 0x0ff) << 8) | (((int) data[i + 2]) & 0x0ff);  
  
            buf.append(legalChars[(d >> 18) & 63]);  
            buf.append(legalChars[(d >> 12) & 63]);  
            buf.append(legalChars[(d >> 6) & 63]);  
            buf.append(legalChars[d & 63]);  
  
            i += 3;  
  
            if (n++ >= 14) {  
                n = 0;  
                buf.append(" ");  
            }  
        }  
  
        if (i == start + len - 2) {  
            int d = ((((int) data[i]) & 0x0ff) << 16) | ((((int) data[i + 1]) & 255) << 8);  
  
            buf.append(legalChars[(d >> 18) & 63]);  
            buf.append(legalChars[(d >> 12) & 63]);  
            buf.append(legalChars[(d >> 6) & 63]);  
            buf.append("=");  
        } else if (i == start + len - 1) {  
            int d = (((int) data[i]) & 0x0ff) << 16;  
  
            buf.append(legalChars[(d >> 18) & 63]);  
            buf.append(legalChars[(d >> 12) & 63]);  
            buf.append("==");  
        }  
  
        return buf.toString();  
    }  
  
    private static int decode(char c) {  
        if (c >= 'A' && c <= 'Z')  
            return ((int) c) - 65;  
        else if (c >= 'a' && c <= 'z')  
            return ((int) c) - 97 + 26;  
        else if (c >= '0' && c <= '9')  
            return ((int) c) - 48 + 26 + 26;  
        else  
            switch (c) {  
            case '+':  
                return 62;  
            case '/':  
                return 63;  
            case '=':  
                return 0;  
            default:  
                throw new RuntimeException("unexpected code: " + c);  
            }  
    }  
  
    /** 
     * Decodes the given Base64 encoded String to a new byte array. The byte array holding the decoded data is returned. 
     */  
  
    public static byte[] decode(String s) {  
  
        ByteArrayOutputStream bos = new ByteArrayOutputStream();  
        try {  
            decode(s, bos);  
        } catch (IOException e) {  
            throw new RuntimeException();  
        }  
        byte[] decodedBytes = bos.toByteArray();  
        try {  
            bos.close();  
            bos = null;  
        } catch (IOException ex) {  
            System.err.println("Error while decoding BASE64: " + ex.toString());  
        }  
        return decodedBytes;  
    }  
  
    private static void decode(String s, OutputStream os) throws IOException {  
        int i = 0;  
  
        int len = s.length();  
  
        while (true) {  
            while (i < len && s.charAt(i) <= ' ')  
                i++;  
  
            if (i == len)  
                break;  
  
            int tri = (decode(s.charAt(i)) << 18) + (decode(s.charAt(i + 1)) << 12) + (decode(s.charAt(i + 2)) << 6) + (decode(s.charAt(i + 3)));  
  
            os.write((tri >> 16) & 255);  
            if (s.charAt(i + 2) == '=')  
                break;  
            os.write((tri >> 8) & 255);  
            if (s.charAt(i + 3) == '=')  
                break;  
            os.write(tri & 255);  
  
            i += 4;  
        }  
    }  
}  


接下来是iPhone端的加密程序,当然是用Ojbective-C写的3DES加密程序,源代码如下: 
Java代码  
//  
//  DES3Util.h  
//  
  
#import <Foundation/Foundation.h>  
  
  
@interface DES3Util : NSObject {  
  
}  
  
// 加密方法  
+ (NSString*)encrypt:(NSString*)plainText;  
  
// 解密方法  
+ (NSString*)decrypt:(NSString*)encryptText;  
  
@end  


Java代码  
//  
//  DES3Util.m  
//  
  
#import "DES3Util.h"  
#import <CommonCrypto/CommonCryptor.h>  
#import "GTMBase64.h"  
  
#define gkey            @"liuyunqiang@lx100$#365#$"  
#define gIv             @"01234567"  
  
@implementation DES3Util  
  
// 加密方法  
+ (NSString*)encrypt:(NSString*)plainText {  
    NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];  
    size_t plainTextBufferSize = [data length];  
    const void *vplainText = (const void *)[data bytes];  
      
    CCCryptorStatus ccStatus;  
    uint8_t *bufferPtr = NULL;  
    size_t bufferPtrSize = 0;  
    size_t movedBytes = 0;  
      
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);  
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));  
    memset((void *)bufferPtr, 0x0, bufferPtrSize);  
      
    const void *vkey = (const void *) [gkey UTF8String];  
    const void *vinitVec = (const void *) [gIv UTF8String];  
      
    ccStatus = CCCrypt(kCCEncrypt,  
                       kCCAlgorithm3DES,  
                       kCCOptionPKCS7Padding,  
                       vkey,  
                       kCCKeySize3DES,  
                       vinitVec,  
                       vplainText,  
                       plainTextBufferSize,  
                       (void *)bufferPtr,  
                       bufferPtrSize,  
                       &movedBytes);  
      
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];  
    NSString *result = [GTMBase64 stringByEncodingData:myData];  
    return result;  
}  
  
// 解密方法  
+ (NSString*)decrypt:(NSString*)encryptText {  
    NSData *encryptData = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];  
    size_t plainTextBufferSize = [encryptData length];  
    const void *vplainText = [encryptData bytes];  
      
    CCCryptorStatus ccStatus;  
    uint8_t *bufferPtr = NULL;  
    size_t bufferPtrSize = 0;  
    size_t movedBytes = 0;  
      
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);  
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));  
    memset((void *)bufferPtr, 0x0, bufferPtrSize);  
      
    const void *vkey = (const void *) [gkey UTF8String];  
    const void *vinitVec = (const void *) [gIv UTF8String];  
      
    ccStatus = CCCrypt(kCCDecrypt,  
                       kCCAlgorithm3DES,  
                       kCCOptionPKCS7Padding,  
                       vkey,  
                       kCCKeySize3DES,  
                       vinitVec,  
                       vplainText,  
                       plainTextBufferSize,  
                       (void *)bufferPtr,  
                       bufferPtrSize,  
                       &movedBytes);  
      
    NSString *result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr   
                                length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding] autorelease];  
    return result;  
}  
  
@end  


iPhone端的加密工具类中引入了“GTMBase64.h”,这是iOS平台的Base64编码工具类,就不在这里贴出相关代码了,需要的百度一下就能找到。 

        这样,JAVA,Android和iPhone三个平台的加密不一致问题就可以解决了。其实,对此问题,还有一种更好的实现方式,那就是用C语言写一套加密程序,这样在iOS平台是可以直接使用C程序的,而在Java和Android端通过JNI去调用C语言编写的加密方法,这样也可以实现3个平台调用同一套加密程序。 
分页工具类
import java.util.List;

public class PageUtils<E> {
	private int pageSize;
	private int pageNo;
	private int currentPageSize;
	private int totalPageNo;
	private int totalResultNum;
	private List<E> itemsList;

	public PageUtils() {
		pageNo = 1;
		pageSize = 10;
	}

	public static void main(String[] args) {
		int pageNo = 1;
		int pageSize = 10;
		int total = 99;
		PageUtils<Integer> pageUtils = new PageUtils<Integer>(pageNo, pageSize,
				total);
		while (pageUtils.hasNext()) {
			System.out.println("pageNo=" + pageUtils.pageNo);
			System.out.println("pageSize=" + pageUtils.pageSize);
			System.out.println("currentPageSize="
					+ pageUtils.getCurrentPageSize());
			pageUtils.next();
		}
	}

	public PageUtils(int pageNo, int pageSize, int totalResultNum) {
		this.pageNo = pageNo;
		this.pageSize = pageSize;
		this.currentPageSize = pageSize;
		this.totalResultNum = totalResultNum;
		if (totalResultNum % pageSize == 0) {
			totalPageNo = totalResultNum / pageSize;
		} else {
			totalPageNo = totalResultNum / pageSize + 1;
		}
	}

	public PageUtils(int pageNo, int pageSize, int totalResultNum,
			List<E> itemsList) {
		this(pageNo, pageSize, totalResultNum);
		this.totalResultNum = totalResultNum;
		if (totalResultNum % pageSize == 0) {
			totalPageNo = totalResultNum / pageSize;
		} else {
			totalPageNo = totalResultNum / pageSize + 1;
		}
	}

	public boolean hasNext() {
		return pageNo - 1 < totalPageNo;
	}

	public void next() {
		pageNo++;
	}

	public int getCurrentPageSize() {
		if (pageNo < totalPageNo) {
			currentPageSize = pageSize;
			return pageSize;
		} else {
			currentPageSize = totalResultNum - (pageNo - 1) * pageSize;
			return currentPageSize;
		}
	}

	public List<E> getDataList() {
		return itemsList;
	}

	public int getTotalResultNum() {
		return totalResultNum;
	}

	public void setTotalResultNum(int totalResultNum) {
		this.totalResultNum = totalResultNum;
	}

	public int getPageSize() {
		return pageSize;
	}

	public int getPageNo() {
		return pageNo;
	}

	public int getTotalPageNo() {
		return totalPageNo;
	}

	public List<E> getItemsList() {
		return itemsList;
	}

	public void setItemsList(List<E> itemsList) {
		if (itemsList.size() >= currentPageSize) {
			this.itemsList = itemsList.subList(0, currentPageSize);
		}
	}

}
获取当前周的周一
public final class DateUtil{
public static Date getMonDayOfCurrentWeak() {
		Calendar calendar = Calendar.getInstance();
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
		Date date=null;
		if(dayOfWeek>Calendar.MONDAY){
			date = DateUtils.addDays(calendar.getTime(), Calendar.MONDAY-dayOfWeek);
			calendar.setTime(date);
		}else if (dayOfWeek==Calendar.SUNDAY) {
			date = DateUtils.addDays(calendar.getTime(), -6);
			calendar.setTime(date);
		}
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		return calendar.getTime();
	}
	
	public static Date getSunDayOfCurrentWeak(){
		Calendar calendar = Calendar.getInstance();
		int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
		Date date=null;
		if(dayOfWeek>Calendar.SUNDAY){
			date = DateUtils.addDays(calendar.getTime(), 8-dayOfWeek);
			calendar.setTime(date);
		}
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}
}
Global site tag (gtag.js) - Google Analytics