4444import org .apache .fory .json .ForyJson ;
4545import org .apache .fory .json .PropertyNamingStrategy ;
4646import org .apache .fory .json .annotation .ForyJsonProvider ;
47+ import org .apache .fory .json .annotation .JsonAnyGetter ;
4748import org .apache .fory .json .annotation .JsonAnyProperty ;
49+ import org .apache .fory .json .annotation .JsonAnySetter ;
4850import org .apache .fory .json .annotation .JsonBase64 ;
4951import org .apache .fory .json .annotation .JsonCodec ;
5052import org .apache .fory .json .annotation .JsonCreator ;
@@ -123,16 +125,14 @@ public static void main(String[] args) {
123125 }
124126
125127 private static void testHostedCodegenConfigurations () {
128+ ForyJson providerJson = newProviderJson ();
129+ ForyJson interpretedJson = newInterpretedJson ();
126130 exerciseCodegenConfiguration (ForyJson .builder ().build (), false );
127- exerciseCodegenConfiguration (newProviderJson (), true );
128- exerciseCodegenConfiguration (
129- ForyJson .builder ()
130- .withFieldMode (true )
131- .withPropertyNamingStrategy (PropertyNamingStrategy .SNAKE_CASE )
132- .registerCodec (CodegenProbeValue .class , new CodegenProbeCodec ())
133- .build (),
134- false );
135- testEmptyMixinCodegen ();
131+ exerciseCodegenConfiguration (providerJson , true );
132+ exerciseCodegenConfiguration (interpretedJson , false );
133+ testEmptyMixin (providerJson , true );
134+ testEmptyMixin (interpretedJson , false );
135+ testInterpretedMetadata (interpretedJson );
136136 testIndependentChildCodegen ();
137137 testExternalModuleMixin ();
138138 }
@@ -147,16 +147,48 @@ private static ForyJson newProviderJson() {
147147 .build ();
148148 }
149149
150- private static void testEmptyMixinCodegen () {
151- CodegenProbeCodec .expect (EmptyMixinTarget .class , true );
152- ForyJson json = newProviderJson ();
150+ private static ForyJson newInterpretedJson () {
151+ return ForyJson .builder ()
152+ .withPropertyNamingStrategy (PropertyNamingStrategy .SNAKE_CASE )
153+ .registerCodec (CodegenProbeValue .class , new CodegenProbeCodec ())
154+ .registerMixin (EmptyMixin .class )
155+ .registerMixin (InterpretedMixin .class )
156+ .build ();
157+ }
158+
159+ private static void testEmptyMixin (ForyJson json , boolean generated ) {
160+ CodegenProbeCodec .expect (EmptyMixinTarget .class , generated );
153161 EmptyMixinTarget value = new EmptyMixinTarget ();
154162 value .probe = new CodegenProbeValue ("empty-mixin" );
155163 String encoded = json .toJson (value );
156164 Preconditions .checkArgument (
157165 json .fromJson (encoded , EmptyMixinTarget .class ).probe .value .equals ("empty-mixin" ));
158166 }
159167
168+ private static void testInterpretedMetadata (ForyJson json ) {
169+ InterpretedMixinTarget mixinValue = new InterpretedMixinTarget ();
170+ mixinValue .setName ("empty-mixin" );
171+ String mixinJson = json .toJson (mixinValue );
172+ Preconditions .checkArgument (
173+ json .fromJson (mixinJson , InterpretedMixinTarget .class ).getName ().equals ("empty-mixin" ));
174+
175+ InterpretedBean bean = new InterpretedBean ();
176+ bean .setName ("bean" );
177+ bean .putExtra ("dynamic" , "extra" );
178+ InterpretedBean decoded = json .fromJson (json .toJson (bean ), InterpretedBean .class );
179+ Preconditions .checkArgument (decoded .getName ().equals ("bean" ));
180+ Preconditions .checkArgument (decoded .extra ().equals (Map .of ("dynamic" , "extra" )));
181+
182+ DirectValueRecord record = new DirectValueRecord ("record-value" );
183+ Preconditions .checkArgument (json .toJson (record ).equals ("\" record-value\" " ));
184+ Preconditions .checkArgument (
185+ json .fromJson ("\" decoded-record\" " , DirectValueRecord .class )
186+ .equals (new DirectValueRecord ("decoded-record" )));
187+ Preconditions .checkArgument (json .toJson (DirectValueEnum .READY ).equals ("\" ready\" " ));
188+ Preconditions .checkArgument (
189+ json .fromJson ("\" done\" " , DirectValueEnum .class ) == DirectValueEnum .DONE );
190+ }
191+
160192 private static void exerciseCodegenConfiguration (ForyJson json , boolean generated ) {
161193 CodegenProbeCodec .expect (CodegenProbeModel .class , generated );
162194 CodegenProbeModel value = new CodegenProbeModel ();
@@ -437,6 +469,7 @@ private static void testValueAnnotations() {
437469 Preconditions .checkArgument (
438470 Arrays .equals (
439471 json .fromJson ("{\" value\" :\" AQID\" }" , Base64Bytes .class ).value , new byte [] {1 , 2 , 3 }));
472+
440473 }
441474
442475 private static void testSubtypes () {
@@ -547,6 +580,49 @@ public EmptyMixinTarget() {}
547580 @ JsonMixin (target = EmptyMixinTarget .class )
548581 public interface EmptyMixin {}
549582
583+ public static final class InterpretedMixinTarget {
584+ private String name ;
585+
586+ public InterpretedMixinTarget () {}
587+
588+ public String getName () {
589+ return name ;
590+ }
591+
592+ public void setName (String name ) {
593+ this .name = name ;
594+ }
595+ }
596+
597+ @ JsonMixin (target = InterpretedMixinTarget .class )
598+ public interface InterpretedMixin {}
599+
600+ @ JsonType
601+ public static final class InterpretedBean {
602+ private String name ;
603+ private final transient Map <String , String > extra = new LinkedHashMap <>();
604+
605+ public InterpretedBean () {}
606+
607+ public String getName () {
608+ return name ;
609+ }
610+
611+ public void setName (String name ) {
612+ this .name = name ;
613+ }
614+
615+ @ JsonAnyGetter
616+ public Map <String , String > extra () {
617+ return extra ;
618+ }
619+
620+ @ JsonAnySetter
621+ public void putExtra (String key , String value ) {
622+ extra .put (key , value );
623+ }
624+ }
625+
550626 /** Hosted-only loader which makes the first equivalent provider unable to compile one model. */
551627 public static final class CodegenRejectingClassLoader extends ClassLoader {
552628 public CodegenRejectingClassLoader () {
@@ -838,6 +914,39 @@ public String value() {
838914 }
839915 }
840916
917+ @ JsonType
918+ public record DirectValueRecord (@ JsonValue String value ) {
919+ @ JsonCreator
920+ public DirectValueRecord {}
921+ }
922+
923+ @ JsonType
924+ public enum DirectValueEnum {
925+ READY ("ready" ),
926+ DONE ("done" );
927+
928+ private final String value ;
929+
930+ DirectValueEnum (String value ) {
931+ this .value = value ;
932+ }
933+
934+ @ JsonValue
935+ public String value () {
936+ return value ;
937+ }
938+
939+ @ JsonCreator
940+ public static DirectValueEnum fromValue (String value ) {
941+ for (DirectValueEnum candidate : values ()) {
942+ if (candidate .value .equals (value )) {
943+ return candidate ;
944+ }
945+ }
946+ throw new IllegalArgumentException (value );
947+ }
948+ }
949+
841950 @ JsonType
842951 public static final class RawValue {
843952 @ JsonRawValue public String body ;
0 commit comments