package com.ym.mec.util.json;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.nio.charset.CharsetDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.alibaba.fastjson.util.TypeUtils;

/**
 * 注意点： 如果存在对象间循环引用问题，解决办法： 将get方法的方法名非标准的名称，
 * 例如将getProductCategory()改成getproductCategory() 或者将属性定义加上transient关键字
 * 最后输出的json串中不包含该对象的信息 OMS系统: solar2.utils 创建者: gaoyong 创建时间： 2013-6-21
 */
public class JsonUtil {

	private static SerializeConfig config = new SerializeConfig();

	public static SerializeConfig getConfig() {
		return config;
	}

	/**
	 * 将json字符串反序列化为指定对象
	 * 
	 * @param <T>
	 * @param text
	 *            json串
	 * @param clazz
	 *            对象的类型
	 * @param features
	 *            特性
	 * @return 特定对象
	 */
	public static <T> T parseObject(String text, Class<T> clazz, Feature... features) {
		return JSON.parseObject(text, clazz, features);
	}

	/**
	 * 将集合型json串转换成集合对象
	 * 
	 * @param <T>
	 * @param text
	 *            json串
	 * @param clazz
	 *            泛型类型
	 * @return 特定对象的集合
	 */
	public static <T> List<T> parseArray(String text, Class<T> clazz) {
		return JSON.parseArray(text, clazz);
	}

	/**
	 * 将字节数组转换成指定对象
	 * 
	 * @param <T>
	 * @param input
	 *            需要转换的内容
	 * @param clazz
	 *            对象类型
	 * @param charsetDecoder
	 *            解码方式
	 * @param features
	 *            特性
	 * @return 特定对象
	 */
	public static <T> T parseObject(byte[] input, Type clazz, CharsetDecoder charsetDecoder, Feature... features) {
		return JSON.parseObject(input, 0, input.length, charsetDecoder, clazz, features);
	}

	/**
	 * 忽略具体对象中的某些属性，将其他属性转换成json字符串
	 * 
	 * @param object
	 *            具体对象
	 * @param ingnoreProperties
	 *            忽略的属性名称，注意大小写
	 * @return json字符串
	 */
	public static String toJsonStringWithIngnore(Object object, final List<String> ingnoreProperties) {
		ValueFilter filter = new ValueFilter() {
			public Object process(Object object, String property, Object propertyValue) {
				if (ingnoreProperties != null) {
					if (ingnoreProperties.contains(property)) {
						return null;
					}
				}
				return propertyValue;
			}
		};
		return toJsonString(object, filter);
	}

	/**
	 * 允许具体对象中的某些属性对应的值转换成json字符串
	 * 
	 * @param object
	 *            具体对象
	 * @param allowProperties
	 *            允许转换成json字符串的属性值对应的属性名称，注意大小写
	 * @return json字符串
	 */
	public static String toJsonStringWithAllow(Object object, final List<String> allowProperties) {
		ValueFilter filter = new ValueFilter() {
			public Object process(Object object, String property, Object propertyValue) {
				if (allowProperties != null) {
					if (allowProperties.contains(property)) {
						return propertyValue;
					}
				}
				return null;
			}
		};
		return toJsonString(object, filter);
	}

	private static String toJsonString(Object obj, ValueFilter filter) {
		SerializeWriter out = new SerializeWriter(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.QuoteFieldNames,
				SerializerFeature.SkipTransientField, SerializerFeature.WriteEnumUsingToString, SerializerFeature.SortField);
		JSONSerializer serializer = new JSONSerializer(out);
		serializer.config(SerializerFeature.WriteEnumUsingToString, false);
		serializer.getValueFilters().add(filter);
		serializer.write(obj);
		return out.toString();
	}

	/**
	 * 将传入的List&lt;JSONObject&gt;改为List&lt;Object&gt;
	 * 
	 * @param jsonList
	 *            传入的List&lt;JSONObject&gt;
	 * @param clazz
	 *            转换的类
	 * @return List&lt;Object&gt;
	 */
	public static <T> List<T> convJOSNList2ObjList(List<JSONObject> jsonList, Class<T> clazz) {
		List<T> objList = new ArrayList<T>();
		if (jsonList != null && jsonList.size() > 0) {
			for (int i = 0; i < jsonList.size(); i++) {
				T val = TypeUtils.castToJavaBean(jsonList.get(i), clazz);
				objList.add(val);
			}
		}
		return objList;
	}

	public static String toJSONString(Object object, SerializerFeature... features) {
		return toJSONString(object, config, null, features);
	}

	public static String toJSONString(Object object, SerializeConfig config, SerializerFeature... features) {
		return toJSONString(object, config, null, features);
	}

	public static String toJSONString(Object object, ValueFilter filter, SerializerFeature... features) {
		return toJSONString(object, config, filter, features);
	}

	public static String toJSONString(Object object, SerializeConfig config, ValueFilter filter, SerializerFeature... features) {

		SerializeWriter out = new SerializeWriter(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteNullStringAsEmpty,
				SerializerFeature.WriteMapNullValue, SerializerFeature.QuoteFieldNames, SerializerFeature.WriteNullNumberAsZero);

		JSONSerializer serializer = new JSONSerializer(out, config);
		for (SerializerFeature feature : features) {
			serializer.config(feature, true);
		}
		if (filter == null) {
			filter = new ValueFilter() {
				@Override
				public Object process(Object object, String name, Object value) {
					if (value instanceof BigDecimal || value instanceof Double || value instanceof Float) {
						return new BigDecimal(value.toString());
					}
					return value;
				}
			};
		}
		serializer.getValueFilters().add(filter);
		serializer.write(object);
		return out.toString();
	}

	/**
	 * 可根据配置参数对目标对象进行转换成json字符串
	 * 
	 * @param obj
	 *            目标对象
	 * @param configs
	 *            序列化配置
	 * @param configs
	 *            特征配置
	 * @return
	 */
	public static String toJsonString(Object obj, SerializeConfig config, Map<SerializerFeature, Boolean> configs) {
		SerializeWriter out = new SerializeWriter();
		JSONSerializer serializer = new JSONSerializer(out, config);
		if (configs != null && configs.size() > 0) {
			for (Entry<SerializerFeature, Boolean> entry : configs.entrySet()) {
				serializer.config(entry.getKey(), entry.getValue());
			}
		}
		serializer.write(obj);
		return out.toString();
	}

	/**
	 * Map转换成对象
	 * @param map 数据源
	 * @param clazz 对象类型
	 * @return
	 */
	public static <T> T toJavaObject(Map<String, Object> map, Class<T> clazz) {
		return TypeUtils.cast(new JSONObject(map), clazz, ParserConfig.getGlobalInstance());
	}
}
