11package com .jsoniter ;
22
3+ import java .lang .reflect .Type ;
34import java .util .*;
45
56class CodegenImplObject {
@@ -46,14 +47,22 @@ public static String genObjectUsingSlice(Class clazz, String cacheKey, Customize
4647 appendVarDef (lines , param );
4748 }
4849 }
50+ append (lines , "com.jsoniter.CodegenAccess.resetExistingObject(iter);" );
4951 append (lines , "com.jsoniter.Slice field = com.jsoniter.CodegenAccess.readObjectFieldAsSlice(iter);" );
5052 append (lines , "boolean once = true;" );
5153 append (lines , "while (once) {" );
5254 append (lines , "once = false;" );
5355 append (lines , "switch (field.len) {" );
5456 String rendered = renderTriTree (cacheKey , trieTree );
5557 for (Binding field : fields ) {
56- rendered = rendered .replace ("_" + field .name + "_" , "obj." + field .name );
58+ if (ctor .parameters .isEmpty () && fields .contains (field )) {
59+ if (shouldReuseObject (field .valueType )) {
60+ rendered = rendered .replace ("_" + field .name + "_" , String .format ("obj.%s" , field .name ));
61+ } else {
62+ rendered = rendered .replace ("_" + field .name + "_" , String .format (
63+ "com.jsoniter.CodegenAccess.setExistingObject(iter, obj.%s);\n obj.%s" , field .name , field .name ));
64+ }
65+ }
5766 }
5867 append (lines , rendered );
5968 append (lines , "}" ); // end of switch
@@ -187,6 +196,7 @@ public static String genObjectUsingHash(Class clazz, String cacheKey, Customized
187196 appendVarDef (lines , param );
188197 }
189198 }
199+ append (lines , "com.jsoniter.CodegenAccess.resetExistingObject(iter);" );
190200 append (lines , "switch (com.jsoniter.CodegenAccess.readObjectFieldAsHash(iter)) {" );
191201 HashSet <Integer > knownHashes = new HashSet <Integer >();
192202 for (Binding field : allBindings ) {
@@ -207,11 +217,7 @@ public static String genObjectUsingHash(Class clazz, String cacheKey, Customized
207217 }
208218 knownHashes .add (intHash );
209219 append (lines , "case " + intHash + ": " );
210- if (ctor .parameters .isEmpty () && fields .contains (field )) {
211- append (lines , String .format ("obj.%s = %s;" , field .name , CodegenImplNative .genField (field , cacheKey )));
212- } else {
213- append (lines , String .format ("_%s_ = %s;" , field .name , CodegenImplNative .genField (field , cacheKey )));
214- }
220+ appendFieldSet (lines , cacheKey , ctor , fields , field );
215221 append (lines , "break;" );
216222 }
217223 }
@@ -229,11 +235,7 @@ public static String genObjectUsingHash(Class clazz, String cacheKey, Customized
229235 }
230236 int intHash = (int ) hash ;
231237 append (lines , "case " + intHash + ": " );
232- if (ctor .parameters .isEmpty () && fields .contains (field )) {
233- append (lines , String .format ("obj.%s = %s;" , field .name , CodegenImplNative .genField (field , cacheKey )));
234- } else {
235- append (lines , String .format ("_%s_ = %s;" , field .name , CodegenImplNative .genField (field , cacheKey )));
236- }
238+ appendFieldSet (lines , cacheKey , ctor , fields , field );
237239 append (lines , "continue;" );
238240 }
239241 }
@@ -254,6 +256,17 @@ public static String genObjectUsingHash(Class clazz, String cacheKey, Customized
254256 .replace ("{{newInst}}" , genNewInstCode (clazz , ctor ));
255257 }
256258
259+ private static void appendFieldSet (StringBuilder lines , String cacheKey , CustomizedConstructor ctor , List <Binding > fields , Binding field ) {
260+ if (ctor .parameters .isEmpty () && fields .contains (field )) {
261+ if (!shouldReuseObject (field .valueType )) {
262+ append (lines , String .format ("com.jsoniter.CodegenAccess.setExistingObject(iter, obj.%s);" , field .name ));
263+ }
264+ append (lines , String .format ("obj.%s = %s;" , field .name , CodegenImplNative .genField (field , cacheKey )));
265+ } else {
266+ append (lines , String .format ("_%s_ = %s;" , field .name , CodegenImplNative .genField (field , cacheKey )));
267+ }
268+ }
269+
257270 private static void appendSetter (List <CustomizedSetter > setters , StringBuilder lines ) {
258271 for (CustomizedSetter setter : setters ) {
259272 lines .append ("obj." );
@@ -283,13 +296,21 @@ private static String genObjectUsingSkip(Class clazz, CustomizedConstructor ctor
283296
284297 private static String genNewInstCode (Class clazz , CustomizedConstructor ctor ) {
285298 StringBuilder code = new StringBuilder ();
299+ if (ctor .parameters .isEmpty ()) {
300+ // nothing to bind, safe to reuse existing object
301+ code .append ("(com.jsoniter.CodegenAccess.existingObject(iter) == null ? " );
302+ }
286303 if (ctor .staticMethodName == null ) {
287304 code .append (String .format ("new %s" , clazz .getCanonicalName ()));
288305 } else {
289306 code .append (String .format ("%s.%s" , clazz .getCanonicalName (), ctor .staticMethodName ));
290307 }
291308 List <Binding > params = ctor .parameters ;
292309 appendInvocation (code , params );
310+ if (ctor .parameters .isEmpty ()) {
311+ // nothing to bind, safe to reuse existing object
312+ code .append (String .format (" : (%s)com.jsoniter.CodegenAccess.existingObject(iter))" , clazz .getCanonicalName ()));
313+ }
293314 return code .toString ();
294315 }
295316
@@ -311,4 +332,14 @@ private static void append(StringBuilder lines, String str) {
311332 lines .append (str );
312333 lines .append ("\n " );
313334 }
335+
336+ public static boolean shouldReuseObject (Type valueType ) {
337+ if (valueType instanceof Class ) {
338+ Class clazz = (Class ) valueType ;
339+ if (clazz .isArray ()) {
340+ return false ;
341+ }
342+ }
343+ return CodegenImplNative .isNative (valueType );
344+ }
314345}
0 commit comments