Java tutorial
/* * Copyright (C) 2008 feilong * * 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 com.discovery.darchrow.tools.jsonlib; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.collections.IteratorUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.discovery.darchrow.date.DatePattern; import com.discovery.darchrow.lang.ArrayUtil; import com.discovery.darchrow.tools.jsonlib.processor.DateJsonValueProcessor; import com.discovery.darchrow.util.Validator; import net.sf.ezmorph.MorpherRegistry; import net.sf.ezmorph.object.DateMorpher; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.JsonConfig; import net.sf.json.processors.JsonValueProcessor; import net.sf.json.util.CycleDetectionStrategy; import net.sf.json.util.JSONUtils; import net.sf.json.util.PropertyFilter; import net.sf.json.util.PropertySetStrategy; import net.sf.json.xml.XMLSerializer; /** * json . * * <h3>??jar:</h3> * * <blockquote> * * <pre> * {@code * <groupId>net.sf.json-lib</groupId> * <artifactId>json-lib</artifactId> * * ?xml,? * <groupId>xom</groupId> * <artifactId>xom</artifactId> * } * </pre> * * </blockquote> * * @author feilong * @version 1.0.5 Jan 26, 2013 8:02:09 PM * @since 1.0.5 */ public final class JsonUtil { /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class); /** Don't let anyone instantiate this class. */ private JsonUtil() { //AssertionError?. ?????. ???. //see Effective Java 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } /** The Constant DEFAULT_JSON_CONFIG. */ private static final JsonConfig DEFAULT_JSON_CONFIG; /** * ?? */ static { // ????Json?? String[] formats = { DatePattern.COMMON_DATE_AND_TIME, DatePattern.COMMON_TIME, DatePattern.COMMON_DATE }; DateMorpher dateMorpher = new DateMorpher(formats); // MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry(); morpherRegistry.registerMorpher(dateMorpher); DEFAULT_JSON_CONFIG = getDefaultJsonConfig(); } //***************************format******************************************************** // [start] format /** * ?,?toJSON, toString(4, 4) . * * @param obj * * @return the string * @see #format(Object, String[]) * @see #format(Object, JsonConfig) */ public static String format(Object obj) { String[] excludes = null; return format(obj, excludes); } /** * ?,?toJSON, toString(4, 4) . * * @param obj * * @param excludes * ???json, excludes isNotNullOrEmpty,?setExcludes * @return if null==obj will return {@code null}; {@link #format(Object, JsonConfig)} * @see #format(Object, JsonConfig) * @see <a href="http://feitianbenyue.iteye.com/blog/2046877">java.lang.ClassCastException: JSON keys must be strings</a> */ public static String format(Object obj, String[] excludes) { return format(obj, excludes, 4, 4); } /** * Format. * * @param obj * the obj * @param excludes * the excludes * @param indentFactor * the indent factor * @param indent * the indent * @return the string */ public static String format(Object obj, String[] excludes, int indentFactor, int indent) { if (null == obj) { return null; } JsonConfig jsonConfig = null; if (Validator.isNotNullOrEmpty(excludes)) { jsonConfig = getDefaultJsonConfig(); jsonConfig.setExcludes(excludes); } JSON json = toJSON(obj, jsonConfig); String string = json.toString(indentFactor, indent); return string; } /** * ??key?formatjson?. * * @param obj * the obj * @param includes * the includes * @return the string * @since 1.0.8 */ public static String formatWithIncludes(Object obj, final String... includes) { if (null == obj) { return null; } JsonConfig jsonConfig = null; if (Validator.isNotNullOrEmpty(includes)) { jsonConfig = getDefaultJsonConfig(); jsonConfig.setJsonPropertyFilter(new PropertyFilter() { @Override public boolean apply(Object source, String name, Object value) { return !ArrayUtil.isContain(includes, name); } }); } return format(obj, jsonConfig); } /** * JsonConfig. * * @return the default json config */ private static JsonConfig getDefaultJsonConfig() { JsonConfig jsonConfig = new JsonConfig(); // ,?? There is a cycle in the hierarchy! jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT); //see net.sf.json.JsonConfig.DEFAULT_EXCLUDES //key "class","declaringClass","metaClass" jsonConfig.setIgnoreDefaultExcludes(true); // ? jsonConfig.registerJsonValueProcessor(Date.class, new DateJsonValueProcessor()); // java.lang.ClassCastException: JSON keys must be strings // see http://feitianbenyue.iteye.com/blog/2046877 jsonConfig.setAllowNonStringKeys(true); return jsonConfig; } /** * ?,?toJSON, toString(4, 4) .<br> * * @param obj * the obj * @param jsonConfig * the json config * @return if null==obj will return {@code null}; else return toJSON(obj, jsonConfig).toString(4, 4) * @see net.sf.json.JsonConfig * @see #toJSON(Object, JsonConfig) * @see net.sf.json.JSON#toString(int, int) * @see #format(Object, JsonConfig, int, int) * @since 1.0.7 */ public static String format(Object obj, JsonConfig jsonConfig) { return format(obj, jsonConfig, 4, 4); } /** * Make a prettyprinted JSON text. * <p> * Warning: This method assumes that the data structure is acyclical. * </p> * * @param obj * the obj * @param jsonConfig * the json config * @param indentFactor * The number of spaces to add to each level of indentation. * @param indent * The indentation of the top level. * @return a printable, displayable, transmittable representation of the object, beginning with { (left brace) and ending with } (right * brace). * @since 1.0.8 */ public static String format(Object obj, JsonConfig jsonConfig, int indentFactor, int indent) { if (null == obj) { return null; } JSON json = toJSON(obj, jsonConfig); String string = json.toString(indentFactor, indent); return string; } // [end] // [start]toBean /** * json,??. * * @param <T> * the generic type * @param json * e.g. {'name':'get','dateAttr':'2009-11-12'}<br> * ? json,?JSONObject<br> * Accepts JSON formatted strings, Maps, DynaBeans and JavaBeans. <br> * ??: {@link JSONObject#fromObject(Object, JsonConfig)} * @param rootClass * e.g. Person.class * @return the t */ public static <T> T toBean(Object json, Class<T> rootClass) { return toBean(json, rootClass, null); } /** * json????Bean. * * @param <T> * the generic type * @param json * e.g. {'data':[{'name':'get'},{'name':'set'}]} * @param rootClass * e.g. MyBean.class * @param classMap * e.g. classMap.put("data", Person.class) * @return Object * @see #toBean(Object, JsonConfig) */ // TODO @SuppressWarnings("unchecked") public static <T> T toBean(Object json, Class<T> rootClass, Map<String, Class<?>> classMap) { JSONObject jsonObject = JSONObject.fromObject(json); JsonConfig jsonConfig = getDefaultJsonConfig(); jsonConfig.setRootClass(rootClass); if (Validator.isNotNullOrEmpty(classMap)) { jsonConfig.setClassMap(classMap); } return (T) toBean(jsonObject, jsonConfig); } /** * json,??. * * @param json * the json * @param jsonConfig * the json config * @return the object * @see net.sf.json.JSONObject#toBean(JSONObject, JsonConfig) */ public static Object toBean(Object json, JsonConfig jsonConfig) { JSONObject jsonObject = JSONObject.fromObject(json); // Ignore missing properties with Json-Lib // ?? Unknown property 'orderIdAndCodeMap' on class 'class // com.baozun.trade.web.controller.payment.result.command.PaymentResultEntity' jsonConfig.setPropertySetStrategy(new PropertyStrategyWrapper(PropertySetStrategy.DEFAULT)); return JSONObject.toBean(jsonObject, jsonConfig); } // [end] // *****************************Array****************************************************** // [start]toArray /** * json??. * * @param json * e.g. ['get',1,true,null] * @return Object[] * @see net.sf.json.JSONArray#fromObject(Object) * @see net.sf.json.JSONArray#toArray() */ public static Object[] toArray(String json) { JSONArray jsonArray = JSONArray.fromObject(json); return jsonArray.toArray(); } /** * json,??. * * @param <T> * the generic type * @param json * e.g. [{'name':'get'},{'name':'set'}] * @param clazz * e.g. Person.class * @return Object[] * @see #toArray(String, Class, Map) */ public static <T> T[] toArray(String json, Class<T> clazz) { return toArray(json, clazz, null); } /** * json????Bean. * * @param <T> * the generic type * @param json * e.g. [{'data':[{'name':'get'}]},{'data':[{'name':'set'}]}] * @param clazz * e.g. MyBean.class * @param classMap * e.g. classMap.put("data", Person.class) * @return T[] * @see net.sf.json.JSONArray#fromObject(Object) * @see net.sf.json.JSONArray#getJSONObject(int) * @see #toBean(Object, Class, Map) * @see java.lang.reflect.Array#newInstance(Class, int) */ public static <T> T[] toArray(String json, Class<T> clazz, Map<String, Class<?>> classMap) { JSONArray jsonArray = JSONArray.fromObject(json); int size = jsonArray.size(); @SuppressWarnings("unchecked") T[] t = (T[]) Array.newInstance(clazz, size); for (int i = 0; i < size; i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); t[i] = toBean(jsonObject, clazz, classMap); } return t; } // [end] // *****************************List******************************************************** // [start]toList /** * json???. * * @param json * e.g. ['get',1,true,null] * @return List * @see net.sf.json.JSONArray#get(int) */ public static List<Object> toList(String json) { JSONArray jsonArray = JSONArray.fromObject(json); int size = jsonArray.size(); List<Object> list = new ArrayList<Object>(); for (int i = 0; i < size; i++) { Object e = jsonArray.get(i); list.add(e); } return list; } /** * json????Bean. * * @param <T> * the generic type * @param json * e.g. [{'name':'get'},{'name':'set'}] * @param clazz * the clazz * @return List * @see #toList(String, Class, Map) */ public static <T> List<T> toList(String json, Class<T> clazz) { return toList(json, clazz, null); } /** * json??????Bean. * * @param <T> * the generic type * @param json * e.g. [{'data':[{'name':'get'}]},{'data':[{'name':'set'}]}] * @param clazz * e.g. MyBean.class * @param classMap * e.g. classMap.put("data", Person.class) * @return List * @see net.sf.json.JSONArray#getJSONObject(int) * @see net.sf.json.JSONArray#fromObject(Object) * @see #toBean(Object, Class, Map) */ // TODO public static <T> List<T> toList(String json, Class<T> clazz, Map<String, Class<?>> classMap) { JSONArray jsonArray = JSONArray.fromObject(json); List<T> list = new ArrayList<T>(); int size = jsonArray.size(); for (int i = 0; i < size; i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); list.add(toBean(jsonObject, clazz, classMap)); } return list; } // [end] // ********************************Map****************************************************** // [start]toMap /** * json??map. * * @param json * e.g. {'name':'get','int':1,'double',1.1,'null':null} * @return Map * @see net.sf.json.JSONObject#get(String) * @see net.sf.json.JSONObject#fromObject(Object) */ public static Map<String, Object> toMap(String json) { JSONObject jsonObject = JSONObject.fromObject(json); Map<String, Object> map = new HashMap<String, Object>(); @SuppressWarnings("unchecked") Iterator<String> keys = jsonObject.keys(); while (keys.hasNext()) { String key = keys.next(); Object value = jsonObject.get(key); map.put(key, value); } return map; } /** * json??mapmapBean. * * @param <T> * the generic type * @param json * e.g. {'data1':{'name':'get'}, 'data2':{'name':'set'}} * @param clazz * e.g. Person.class * @return Map * @see #toMap(String, Class, Map) */ public static <T> Map<String, T> toMap(String json, Class<T> clazz) { return toMap(json, clazz, null); } /** * json??mapmapBean??Bean. * * @param <T> * the generic type * @param json * e.g. {'mybean':{'data':[{'name':'get'}]}} * @param clazz * e.g. MyBean.class * @param classMap * e.g. classMap.put("data", Person.class) * @return Map * @see net.sf.json.JSONObject#keys() * @see #toBean(Object, Class, Map) */ // TODO public static <T> Map<String, T> toMap(String json, Class<T> clazz, Map<String, Class<?>> classMap) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("in json:{}", json); } JSONObject jsonObject = JSONObject.fromObject(json); Map<String, T> map = new HashMap<String, T>(); @SuppressWarnings("unchecked") Iterator<String> keys = jsonObject.keys(); while (keys.hasNext()) { String key = keys.next(); Object value = jsonObject.get(key); if (LOGGER.isDebugEnabled()) { LOGGER.debug("key:{} value:{}", key, value); } map.put(key, toBean(value, clazz, classMap)); } return map; } // [end] // [start]toJSON /** * Bean?Map?????Json. * * @param obj * the obj * @return the jSON * @see #toJSON(Object, JsonConfig) */ public static JSON toJSON(Object obj) { return toJSON(obj, null); } /** * Bean?Map?????Json. * * @param obj * the obj * @param jsonConfig * the json config * @return the jSON * @see net.sf.json.JSONArray#fromObject(Object, JsonConfig) * @see net.sf.json.JSONObject#fromObject(Object, JsonConfig) * @see net.sf.json.util.JSONUtils#isArray(Object) * @see java.lang.Class#isEnum() * @see net.sf.json.JsonConfig#registerJsonValueProcessor(Class, JsonValueProcessor) * @see org.apache.commons.collections.IteratorUtils#toList(Iterator) * @see org.apache.commons.collections.IteratorUtils#toList(Iterator, int) */ public static JSON toJSON(Object obj, JsonConfig jsonConfig) { if (null == jsonConfig) { jsonConfig = DEFAULT_JSON_CONFIG; } // obj instanceof Collection || obj instanceof Object[] if (JSONUtils.isArray(obj) || // obj instanceof Enum || // obj.getClass().isEnum() null// object'isanEnum.UseJSONArrayinstead obj instanceof Iterator) { if (obj instanceof Iterator) { Collection<?> list = IteratorUtils.toList((Iterator<?>) obj); obj = list; } //Accepts JSON formatted strings, arrays, Collections and Enums. return JSONArray.fromObject(obj, jsonConfig); } //Accepts JSON formatted strings, Maps, DynaBeans and JavaBeans. return JSONObject.fromObject(obj, jsonConfig); } // [end] //*******************************objectToXML************************************************* // [start]objectToXML /** * json???(collection map)?Bean??XML<br> * XMLSerializer API http://json-lib.sourceforge.net/apidocs/net/sf/json/xml/XMLSerializer.html ?<br> * http://json-lib.sourceforge.net/xref-test/net/sf/json/xml/TestXMLSerializer_writes.html<br> * http://json-lib.sourceforge.net/xref-test/net/sf/json/xml/TestXMLSerializer_writes.html * * @param object * the object * @return xml * @see #objectToXML(Object, String) */ public static String objectToXML(Object object) { return objectToXML(object, null); } /** * Object to xml<br> * : * <ul> * <li>? {@code <?xml version="1.0" encoding="UTF-8"? >}</li> * <li>??</li> * <li>,? {@code <additionalData></additionalData>} ,? {@code <additionalData/>}</li> * </ul> * * @param object * the object * @param encoding * the encoding * @return the string * @see #toJSON(Object) * @see net.sf.json.xml.XMLSerializer#write(JSON) * @see net.sf.json.xml.XMLSerializer#write(JSON, String) */ public static String objectToXML(Object object, String encoding) { JSON json = toJSON(object); XMLSerializer xmlSerializer = new XMLSerializer(); // xmlSerializer.setRootName("outputPaymentPGW"); // xmlSerializer.setTypeHintsEnabled(true); // xmlSerializer.setTypeHintsCompatibility(true); // xmlSerializer.setSkipWhitespace(false); if (Validator.isNotNullOrEmpty(encoding)) { return xmlSerializer.write(json, encoding); } return xmlSerializer.write(json); } // [end] // [start]xmlToJSON /** * XML?json. * * @param xml * the xml * @return String * @see net.sf.json.xml.XMLSerializer#read(String) */ public static JSON xmlToJSON(String xml) { XMLSerializer xmlSerializer = new XMLSerializer(); JSON json = xmlSerializer.read(xml); return json; } // [end] }