public class Test implements Serializable { private static final long serialVersionUID = 2010307013874058143L; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public C1 c1; public C1 getC1() { return c1; } public void setC1(C1 c1) { this.c1 = c1; } public class C1 { public String name; public C1() { } public String getName() { return name; } public void setName(String name) { this.name = name; } } }
调用序列化与反序列化:
public static String toJson(Object obj) { try { return JSON.json(obj); } catch (IOException e) { log.error("class to json is error!", e); } return null; } public static <T> T formJson(String json, Class<T> classOfT) { try { return JSON.parse(json, classOfT); } catch (ParseException e) { log.error("json to class is error! "+classOfT.getName(), e); } return null; } public static void main(String[] args) { Test test = new Test(); System.out.println(toJson(test)); String json = "{\"name\":\"test\",\"c1\":{\"name\":\"c1\"}}"; test = formJson(json, Test.class); System.out.println(test.getC1().getName()); }
输出:
{"c1":null,"name":null,"C1":null} Exception in thread "main" java.lang.NullPointerException ERROR 2018-03-06 15:19:05.418 [xxx] (): json to class is error! Test com.alibaba.dubbo.common.json.ParseException: java.lang.InstantiationException: Test$C1 java.lang.InstantiationException: Test$C1 at java.lang.Class.newInstance(Class.java:359) at com.alibaba.dubbo.common.json.J2oVisitor.objectBegin(J2oVisitor.java:119) at com.alibaba.dubbo.common.json.JSON.parse(JSON.java:745) at com.alibaba.dubbo.common.json.JSON.parse(JSON.java:227) at com.alibaba.dubbo.common.json.JSON.parse(JSON.java:210)
//下面是com.alibaba.dubbo.common.json.J2oVisitor的方法 public void objectBegin() throws ParseException { mStack.push(mValue); mStack.push(mType); mStack.push(mWrapper);
if( mType == Object.class || Map.class.isAssignableFrom(mType) ) { if (! mType.isInterface() && mType != Object.class) { try { mValue = mType.newInstance(); } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } else if (mType == ConcurrentMap.class) { mValue = new ConcurrentHashMap<String, Object>(); } else { mValue = new HashMap<String, Object>(); } mWrapper = null; } else { try { mValue = mType.newInstance(); mWrapper = Wrapper.getWrapper(mType); } catch(IllegalAccessException e){ throw new ParseException(StringUtils.toString(e)); } catch(InstantiationException e){ throw new ParseException(StringUtils.toString(e)); } } } //下面是Class的方法 public T newInstance() throws InstantiationException, IllegalAccessException { if (System.getSecurityManager() != null) { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); }
// NOTE: the following code may not be strictly correct under // the current Java memory model.
// Constructor lookup if (cachedConstructor == null) { if (this == Class.class) { throw new IllegalAccessException( "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; final Constructor<T> c = getConstructor0(empty, Member.DECLARED); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Void>() { public Void run() { c.setAccessible(true); return null; } }); cachedConstructor = c; } catch (NoSuchMethodException e) { throw new InstantiationException(getName()); } } Constructor<T> tmpConstructor = cachedConstructor; // Security check (same as in java.lang.reflect.Constructor) int modifiers = tmpConstructor.getModifiers(); if (!Reflection.quickCheckMemberAccess(this, modifiers)) { Class<?> caller = Reflection.getCallerClass(); if (newInstanceCallerCache != caller) { Reflection.ensureMemberAccess(caller, this, null, modifiers); newInstanceCallerCache = caller; } } // Run constructor try { return tmpConstructor.newInstance((Object[])null); } catch (InvocationTargetException e) { Unsafe.getUnsafe().throwException(e.getTargetException()); // Not reached return null; } }
public class Test$C1 { public String name; public Test$C1(Test paramTest) {} public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
Uses the constructor represented by this Constructor object to create and initialize a new instance of the constructor's declaring class, with the specified initialization parameters. Individual parameters are automatically unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary. If the number of formal parameters required by the underlying constructor is 0, the supplied initargs array may be of length 0 or null.
If the constructor's declaring class is an inner class in a non-static context, the first argument to the constructor needs to be the enclosing instance; see The Java Language Specification, section 15.9.3.
If the required access and argument checks succeed and the instantiation will proceed, the constructor's declaring class is initialized if it has not already been initialized.
If the constructor completes normally, returns the newly created and initialized instance.
具体关注这句:If the constructor’s declaring class is an inner class in a non-static context, the first argument to the constructor needs to be the enclosing instance; see The Java Language Specification, section 15.9.3
public class Test implements Serializable { private static final long serialVersionUID = 2010307013874058143L; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public C1 c1; public C1 getC1() { return c1; } public void setC1(C1 c1) { this.c1 = c1; } public class C1 { public String name; public C1() { } public String getName() { return name; } public void setName(String name) { this.name = name; } } }
ps.注意我这里的内部类C1是non-static的
gson开启内部类序列化
public static void main(String[] args) { Gson gson = new GsonBuilder().serializeNulls().create(); Test test = new Test(); test.setName("序列化参数name"); System.out.println(gson.toJson(test)); String json = "{\"name\":\"test\",\"c1\":{\"name\":\"c1\"}}"; test = gson.fromJson(json, Test.class); System.out.println(test.getC1() == null ? "null" : test.getC1().getName()); }
ps.默认InnerClassSerialization就是开启的
输出:
{"name":"序列化参数name","c1":null} c1
gson禁用内部类序列化
public static void main(String[] args) { Gson gson = new GsonBuilder().serializeNulls().disableInnerClassSerialization().create(); Test test = new Test(); test.setName("序列化参数name"); System.out.println(gson.toJson(test)); String json = "{\"name\":\"test\",\"c1\":{\"name\":\"c1\"}}"; test = gson.fromJson(json, Test.class); System.out.println(test.getC1() == null ? "null" : test.getC1().getName()); }