1010import java .util .HashMap ;
1111import java .util .HashSet ;
1212import java .util .Map ;
13+ import java .util .Optional ;
1314import java .util .Set ;
1415
1516import org .jboss .jandex .ClassInfo ;
1617import org .jboss .jandex .FieldInfo ;
1718import org .jboss .jandex .IndexView ;
1819import org .jboss .jandex .MethodInfo ;
20+ import org .jboss .jandex .VoidType ;
1921
22+ import com .fasterxml .jackson .annotation .JsonValue ;
2023import com .fasterxml .jackson .core .JsonGenerator ;
2124import com .fasterxml .jackson .core .SerializableString ;
2225import com .fasterxml .jackson .core .io .SerializedString ;
@@ -183,15 +186,27 @@ protected boolean createSerializationMethod(ClassInfo classInfo, ClassCreator cl
183186 "com.fasterxml.jackson.databind.SerializerProvider" )
184187 .setModifiers (ACC_PUBLIC )
185188 .addException (IOException .class );
189+
186190 boolean valid = serializeObject (classInfo , classCreator , beanClassName , serialize );
187191 serialize .returnVoid ();
188192 return valid ;
189193 }
190194
191195 private boolean serializeObject (ClassInfo classInfo , ClassCreator classCreator , String beanClassName ,
192196 MethodCreator serialize ) {
197+
198+ var jsonValueFieldSpecs = jsonValueFieldSpecs (classInfo );
199+ if (jsonValueFieldSpecs == null ) {
200+ return false ;
201+ }
202+
193203 SerializationContext ctx = new SerializationContext (serialize , beanClassName );
194204
205+ if (jsonValueFieldSpecs .isPresent ()) {
206+ serializeJsonValue (ctx , serialize , jsonValueFieldSpecs .get ());
207+ return true ;
208+ }
209+
195210 // jsonGenerator.writeStartObject();
196211 MethodDescriptor writeStartObject = MethodDescriptor .ofMethod (JSON_GEN_CLASS_NAME , "writeStartObject" , "void" );
197212 serialize .invokeVirtualMethod (writeStartObject , ctx .jsonGenerator );
@@ -212,6 +227,26 @@ private boolean serializeObject(ClassInfo classInfo, ClassCreator classCreator,
212227 return valid ;
213228 }
214229
230+ private Optional <FieldSpecs > jsonValueFieldSpecs (ClassInfo classInfo ) {
231+ var jsonValueMethodFieldSpecs = classInfo .methods ().stream ()
232+ .filter (mi -> mi .annotation (JsonValue .class ) != null )
233+ .filter (this ::isJsonValueMethod ).findFirst ().map (FieldSpecs ::new );
234+ var jsonValueFieldFieldSpecs = classInfo .fields ().stream ()
235+ .filter (f -> f .annotation (JsonValue .class ) != null )
236+ .findFirst ().map (FieldSpecs ::new );
237+
238+ if (jsonValueFieldFieldSpecs .isPresent ()) {
239+ return jsonValueMethodFieldSpecs .isPresent () ? null : jsonValueFieldFieldSpecs ;
240+ }
241+ return jsonValueMethodFieldSpecs ;
242+ }
243+
244+ private void serializeJsonValue (SerializationContext ctx , MethodCreator bytecode , FieldSpecs jsonValueFieldSpecs ) {
245+ String typeName = jsonValueFieldSpecs .fieldType .toString ();
246+ ResultHandle arg = jsonValueFieldSpecs .toValueReaderHandle (bytecode , ctx .valueHandle );
247+ writeFieldValue (jsonValueFieldSpecs , bytecode , ctx , typeName , arg , null );
248+ }
249+
215250 private boolean serializeObjectData (ClassInfo classInfo , ClassCreator classCreator , MethodCreator serialize ,
216251 SerializationContext ctx , Set <String > serializedFields ) {
217252 return serializeFields (classInfo , classCreator , serialize , ctx , serializedFields ) &&
@@ -258,6 +293,12 @@ private FieldSpecs fieldSpecsFromMethod(MethodInfo methodInfo) {
258293 return !Modifier .isStatic (methodInfo .flags ()) && isGetterMethod (methodInfo ) ? new FieldSpecs (methodInfo ) : null ;
259294 }
260295
296+ private boolean isJsonValueMethod (MethodInfo methodInfo ) {
297+ return Modifier .isPublic (methodInfo .flags ()) && !Modifier .isStatic (methodInfo .flags ())
298+ && methodInfo .parametersCount () == 0
299+ && !methodInfo .returnType ().equals (VoidType .VOID );
300+ }
301+
261302 private boolean isGetterMethod (MethodInfo methodInfo ) {
262303 String methodName = methodInfo .name ();
263304 return Modifier .isPublic (methodInfo .flags ()) && !Modifier .isStatic (methodInfo .flags ())
@@ -273,25 +314,36 @@ private void writeField(ClassInfo classInfo, FieldSpecs fieldSpecs, BytecodeCrea
273314 bytecode = checkInclude (bytecode , ctx , arg );
274315
275316 String typeName = fieldSpecs .fieldType .name ().toString ();
317+ writeFieldValue (fieldSpecs , bytecode , ctx , typeName , arg , pkgName );
318+ }
319+
320+ private void writeFieldValue (FieldSpecs fieldSpecs , BytecodeCreator bytecode , SerializationContext ctx , String typeName ,
321+ ResultHandle arg , String pkgName ) {
276322 String primitiveMethodName = writeMethodForPrimitiveFields (typeName );
277323
278324 if (primitiveMethodName != null ) {
279325 BytecodeCreator primitiveBytecode = JacksonSerializationUtils .isBoxedPrimitive (typeName )
280326 ? bytecode .ifNotNull (arg ).trueBranch ()
281327 : bytecode ;
282- writeFieldName (fieldSpecs , primitiveBytecode , ctx .jsonGenerator , pkgName );
328+
329+ if (pkgName != null ) {
330+ writeFieldName (fieldSpecs , primitiveBytecode , ctx .jsonGenerator , pkgName );
331+ }
332+
283333 MethodDescriptor primitiveWriter = MethodDescriptor .ofMethod (JSON_GEN_CLASS_NAME , primitiveMethodName , "void" ,
284334 fieldSpecs .writtenType ());
285335 primitiveBytecode .invokeVirtualMethod (primitiveWriter , ctx .jsonGenerator , arg );
286- return ;
287- }
288336
289- registerTypeToBeGenerated (fieldSpecs .fieldType , typeName );
337+ } else {
338+ if (pkgName != null ) {
339+ registerTypeToBeGenerated (fieldSpecs .fieldType , typeName );
340+ writeFieldName (fieldSpecs , bytecode , ctx .jsonGenerator , pkgName );
341+ }
290342
291- writeFieldName ( fieldSpecs , bytecode , ctx . jsonGenerator , pkgName );
292- MethodDescriptor writeMethod = MethodDescriptor . ofMethod ( JSON_GEN_CLASS_NAME , "writePOJO" ,
293- void . class , Object . class );
294- bytecode . invokeVirtualMethod ( writeMethod , ctx . jsonGenerator , arg );
343+ MethodDescriptor writeMethod = MethodDescriptor . ofMethod ( JSON_GEN_CLASS_NAME , "writePOJO" ,
344+ void . class , Object . class );
345+ bytecode . invokeVirtualMethod ( writeMethod , ctx . jsonGenerator , arg );
346+ }
295347 }
296348
297349 private static BytecodeCreator checkInclude (BytecodeCreator bytecode , SerializationContext ctx , ResultHandle arg ) {
0 commit comments