高效的JSON转换工具

       在网上搜索了一番发现用json-lib进行json格式转换的还真不少,但是经过测试性能不太令人满意,同类工具中还有个后起

之秀那就是jackson,单从性能上说要比json-lib好很多,于是在项目中就决定用jackson了。
     但是关于jackson的资料在网上相比不是很多,于是到了官方网站看了看,把源码下载下来。帮助文档做的不太好,也没有

个现成的例子供参考。不过还好,最后在官方网(http://jackson.codehaus.org/)站的某个角落里找到了一些例子, 我在原来例子的基础上稍加改动封装了一个工具,供网友们参考,有不当之处还望拍砖指正。

      为性能考虑尽量少的向客户端发送数据,所以在Bean到JSON转换的时候把不需要的字段过滤掉,要完成这个功能我们必须自定义一个实现StdSerializerProvider接口的序列化器BzStdSerializerProvider,然后把这个序列化器赋给ObjectMapper即可,下面就把整个具体实现贴出来:

package com.bzlccn.oa.common.json.jackson; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Vector; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.SerializerFactory; import org.codehaus.jackson.map.SerializerProvider; import org.codehaus.jackson.map.introspect.BasicBeanDescription; import org.codehaus.jackson.map.ser.BeanPropertyWriter; import org.codehaus.jackson.map.ser.BeanSerializer; import org.codehaus.jackson.map.ser.CustomSerializerFactory; import org.codehaus.jackson.map.ser.StdSerializerProvider; /** * json处理工具集 * * @author rain * */ public class CustomSerialization { private static final ObjectMapper mapper = new ObjectMapper(); static class FilteredWriter extends BeanPropertyWriter { public FilteredWriter(BeanPropertyWriter w) { super(w); } public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception { BzStdSerializerProvider myprov = (BzStdSerializerProvider) prov; HashMap<?, ?> filter = myprov.getCurrentFilter(); if (filter == null) { super.serializeAsField(bean, jgen, prov); } else if (filter.containsKey(this._name)) { Object subfilter = filter.get(this._name); myprov.pushFilter(HashMap.class.isAssignableFrom(subfilter .getClass()) ? (HashMap<?, ?>) subfilter : null); super.serializeAsField(bean, jgen, prov); myprov.popFilter(); } } } static class CustomBeanFactory extends CustomSerializerFactory { @Override protected BeanSerializer processViews(SerializationConfig config, BasicBeanDescription beanDesc, BeanSerializer ser, List<BeanPropertyWriter> props) { ser = super.processViews(config, beanDesc, ser, props); BeanPropertyWriter[] writers = props .toArray(new BeanPropertyWriter[props.size()]); for (int i = 0; i < writers.length; ++i) { writers[i] = new FilteredWriter(writers[i]); } ser = ser.withFiltered(writers); return ser; } } static class BzStdSerializerProvider extends StdSerializerProvider { private HashMap<?, ?> _filter; private Vector<HashMap<?, ?>> _stack = new Vector<HashMap<?, ?>>(); public BzStdSerializerProvider() { super(); } public BzStdSerializerProvider(HashMap<?, ?> filter) { super(); _filter = filter; } protected BzStdSerializerProvider(SerializationConfig config, StdSerializerProvider src, SerializerFactory f) { super(config, src, f); } protected BzStdSerializerProvider(SerializationConfig config, StdSerializerProvider src, SerializerFactory f, HashMap<?, ?> filter) { super(config, src, f); _filter = filter; } protected StdSerializerProvider createInstance( SerializationConfig config, SerializerFactory jsf) { return new BzStdSerializerProvider(config, this, jsf, _filter); } public HashMap<?, ?> getCurrentFilter() { if (_stack.isEmpty()) return _filter; return _stack.lastElement(); } public void pushFilter(HashMap<?, ?> filter) { _stack.add(filter); } public void popFilter() { if (!_stack.isEmpty()) { _stack.removeElement(_stack.lastElement()); } } } /** * 把对应的bean转换成json串,并可以对多余的字段进行过滤 * @param bean 要转换的bean * @param filter 过滤字符串 * @return */ public static String writeBean(ObjectMapper mapper,Object bean, String filter) { try { if (bean != null && filter != null) { HashMap<?, ?> filterMap = mapper.readValue(filter, HashMap.class); mapper.setSerializerProvider(new BzStdSerializerProvider( filterMap)); mapper.setSerializerFactory(new CustomBeanFactory()); return mapper.viewWriter(String.class).writeValueAsString(bean); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 把对应的bean转换成json串,并可以对多余的字段进行过滤 * @param bean 要转换的bean * @param filter 过滤字符串 * @return */ public static String writeBean(Object bean, String filter) { try { if (bean != null && filter != null) { HashMap<?, ?> filterMap = mapper.readValue(filter, HashMap.class); mapper.setSerializerProvider(new BzStdSerializerProvider( filterMap)); mapper.setSerializerFactory(new CustomBeanFactory()); return mapper.viewWriter(String.class).writeValueAsString(bean); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } /** * 把javabean转换成json串 * @param bean * @return */ public static String writeBean(Object bean) { try { if (bean != null) { return mapper.writeValueAsString(bean); } } catch (JsonParseException e) { e.printStackTrace(); } catch (JsonMappingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } }

上述类只是一个实现过滤功能的Bean to Json的工具类,当然你也可以继续扩展。下面我们继续完善,提供一个综合的,支持过滤的,能JSON互转的,转换内容以及方法能自定义的一个综合JSON转换工具,当然要有上边的类做支持了。这是一个基于接口的动态代理的实现,

具体代码如下。

package com.bzlccn.oa.common.json.jackson; import java.io.*; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.net.URL; import java.util.LinkedHashMap; import java.util.Map; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.RuntimeJsonMappingException; import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.type.TypeFactory; import org.codehaus.jackson.type.JavaType; public class JacksonProxy { private JacksonProxy() {} public static <T> T newProxyInstance(Class<T> type, Class<?>... additionalTypes) { ObjectMapper objectMapper = new ObjectMapper(); return newProxyInstance(objectMapper, type, additionalTypes); } public static <T> T newProxyInstance(ObjectMapper objectMapper, Class<T> type, Class<?>... additionalTypes) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) classLoader = type.getClassLoader(); Class<?>[] interfaces = new Class<?>[additionalTypes.length + 1]; interfaces[0] = type; System.arraycopy(additionalTypes, 0, interfaces, 1, additionalTypes.length); InvocationHandler invocationHandler = new JsonInvocationHandler(objectMapper, interfaces); Object proxy = Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); return type.cast(proxy); } public static ObjectMapper getObjectMapper(Object proxy) { InvocationHandler invocationHandler = Proxy.getInvocationHandler(proxy); if (invocationHandler instanceof JsonInvocationHandler) { JsonInvocationHandler jsonInvocationHandler = (JsonInvocationHandler) invocationHandler; return jsonInvocationHandler.getObjectMapper(); } throw new IllegalArgumentException("Proxy is not a JacksonProxy"); } public static class JsonInvocationHandler implements InvocationHandler { private final ObjectMapper objectMapper; private final Map<Method, Handler> handlers = new LinkedHashMap<Method, Handler>(); public JsonInvocationHandler(ObjectMapper objectMapper, Class<?>[] interfaces) { if (objectMapper == null) throw new NullPointerException("mapper is null"); if (interfaces == null) throw new NullPointerException("type is null"); this.objectMapper = objectMapper; for (Class<?> type : interfaces) { for (Method method : type.getMethods()) { String name = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); Class<?> returnType = method.getReturnType(); if (name.startsWith("read")) { if (parameterTypes.length == 1 && !returnType.equals(Void.TYPE)) { ReadHandler handler = new ReadHandler(objectMapper, method.getGenericReturnType(), canThrowIOException(method)); handlers.put(method, handler); } } else if (name.startsWith("write")) { if (Void.TYPE.equals(returnType)) { WriteHandler handler = new WriteHandler(objectMapper, null, canThrowIOException(method)); handlers.put(method, handler); }else{ WriteHandler handler = new WriteHandler(objectMapper, returnType, canThrowIOException(method)); handlers.put(method, handler); } } } } } public ObjectMapper getObjectMapper() { return objectMapper; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Handler handler = handlers.get(method); if (handler == null) { throw new UnsupportedOperationException(method.toString()); } return handler.invoke(args); } private static boolean canThrowIOException(Method method) { for (Class<?> exceptionType : method.getExceptionTypes()) { if (IOException.class.isAssignableFrom(exceptionType)) { return true; } } return false; } } private static interface Handler { Object invoke(Object[] args) throws Throwable; } private static class ReadHandler implements Handler { private final ObjectMapper mapper; private final JavaType javaType; private final boolean canThrowIoException; public ReadHandler(ObjectMapper mapper, Type type, boolean canThrowIoException) { this.mapper = mapper; javaType = TypeFactory.fromType(type); this.canThrowIoException = canThrowIoException; } @Override public Object invoke(Object[] args) throws Throwable { try { Object source = args[0]; return read(source); } catch (IOException e) { if (canThrowIoException) { throw e; } else { throw new RuntimeJsonMappingException((JsonMappingException) e); } } } public Object read(Object source) throws IOException { if (source == null) { throw new NullPointerException("source is null"); } JsonParser parser; if (source instanceof String) { String string = (String) source; parser = mapper.getJsonFactory().createJsonParser(string); } else if (source instanceof byte[]) { byte[] bytes = (byte[]) source; parser = mapper.getJsonFactory().createJsonParser(bytes); } else if (source instanceof Reader) { Reader reader = (Reader) source; parser = mapper.getJsonFactory().createJsonParser(reader); parser.disableFeature(JsonParser.Feature.AUTO_CLOSE_SOURCE); } else if (source instanceof InputStream) { InputStream inputStream = (InputStream) source; parser = mapper.getJsonFactory().createJsonParser(inputStream); parser.disableFeature(JsonParser.Feature.AUTO_CLOSE_SOURCE); } else if (source instanceof File) { File file = (File) source; parser = mapper.getJsonFactory().createJsonParser(file); } else if (source instanceof URL) { URL url = (URL) source; parser = mapper.getJsonFactory().createJsonParser(url); } else { throw new UnsupportedOperationException("Unsupported source type " + source.getClass() + " for JSON read method"); } try { return mapper.readValue(parser, javaType); } finally { parser.close(); } } } private static class WriteHandler implements Handler { private final ObjectMapper mapper; private final Class<?> returnType; private final boolean canThrowIoException; public WriteHandler(ObjectMapper mapper, Class<?> returnType, boolean canThrowIoException) { this.mapper = mapper; this.returnType = returnType; this.canThrowIoException = canThrowIoException; } @Override public Object invoke(Object[] args) throws Throwable { try { Object value = args[0]; if (returnType == null) { Object target = args[1]; write(value, target); return null; } else if (String.class.equals(returnType)) { if (args.length>=2&&args[1]!=null) {//如果返回类型是String且有第二个参数,那么就默认第二个参数为过滤参数 return CustomSerialization.writeBean(value, args[1].toString()); } else { StringWriter stringWriter = new StringWriter(); write(value, stringWriter); return stringWriter.toString(); } } else if (byte[].class.equals(returnType)) { ByteArrayOutputStream out = new ByteArrayOutputStream(); write(value, out); return out.toByteArray(); } else { throw new UnsupportedOperationException("Unsupported target type " + returnType + " for JSON write method"); } } catch (IOException e) { if (canThrowIoException) { throw e; } else { throw new RuntimeJsonMappingException((JsonMappingException) e); } } } public void write(Object value, Object target) throws IOException { if (target == null) { throw new NullPointerException("target is null"); } JsonGenerator generator; if (target instanceof Writer) { Writer writer = (Writer) target; generator = mapper.getJsonFactory().createJsonGenerator(writer); generator.disableFeature(JsonGenerator.Feature.AUTO_CLOSE_TARGET); } else if (target instanceof OutputStream) { OutputStream outputStream = (OutputStream) target; generator = mapper.getJsonFactory().createJsonGenerator(outputStream, JsonEncoding.UTF8); generator.disableFeature(JsonGenerator.Feature.AUTO_CLOSE_TARGET); } else if (target instanceof File) { File file = (File) target; generator = mapper.getJsonFactory().createJsonGenerator(file, JsonEncoding.UTF8); } else { throw new UnsupportedOperationException("Unsupported target type " + target.getClass() + " for JSON write method"); } if (mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.INDENT_OUTPUT)) { generator.useDefaultPrettyPrinter(); } try { mapper.writeValue(generator, value); } finally { generator.close(); } } } }

接口代码:

 

 package com.bzlccn.oa.common.json.jackson; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.util.List; import java.util.Map; public interface JsonInterface { String readString(String value) throws IOException; int readInt(String value); Integer readInteger(String value); Object readBean(String value); List<String> readStringList(String value) throws IOException; int[] readIntArray(String value); List<Integer> readIntegerList(String value); List<Short> readShortList(String value); List<Object> readBeanList(String value); List<Map<String,Object>> readBeanByMap(String value); List<Object> readBeanList(byte[] value); List<Object> readBeanList(Reader value); List<Object> readBeanList(InputStream value); String writeString(String value) throws IOException; String writeInt(int value); String writeInteger(Integer value); String writeBean(Object value); String writeBean(Object value,String filter); String writeStringList(List<String> value) throws IOException; String writeIntArray(int[] value); String writeIntegerList(List<Integer> value); String writeBeanList(List<?> value); String writeBeanList(List<?> value,String filter); void writeBeanList(List<?> value, Writer writer); void writeBeanList(List<?> value, OutputStream writer); byte[] writeBeanListToByteArray(List<?> value); }

最终供调用的工具代码:

package com.bzlccn.oa.common.json; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.util.ArrayList; import java.util.List; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig.Feature; import com.bzlccn.oa.common.json.jackson.JacksonProxy; import com.bzlccn.oa.common.json.jackson.JsonInterface; /** * json处理工具集 * * @author rain * */ public class JsonUtil{ private static JsonInterface json; static{ ObjectMapper mapper = new ObjectMapper(); mapper.configure(Feature.INDENT_OUTPUT, true); json = JacksonProxy.newProxyInstance(mapper, JsonInterface.class); } public static JsonInterface getTool(){ return json; } //********************************************************************************** static class ViewBean { public String name; public String value; public String secret; public ViewBean sibling; public ViewBeanChild child; public ViewBean(String name, String value, String secret) { this.name = name; this.value = value; this.secret = secret; child = new ViewBeanChild(); } } static class ViewBeanChild { public long id = 123; public String name = "child"; public String address = "123 Street"; } public static void main(String[] args) throws Exception { ViewBean bean = new ViewBean("mr bean", null, "secret!"); bean.sibling = new ViewBean("sibling", "lala", "boooo"); String filter = "{/"name/":0,/"value/":0,/"sibling/":{/"name/":0}, /"child/":{/"id/":0,/"address/":0}}"; System.out.println(json.writeBean(bean,filter)); } }

这样实现的一个好处就是方法可以自定义,向把json串转换成什么类型的bean只要在JsonInterface接口中申明就可以了。这个是基于

jackson1.5版本实现的。

你可能感兴趣的:(高效的JSON转换工具)