1515import org .hibernate .metamodel .mapping .internal .EmbeddedAttributeMapping ;
1616import org .hibernate .metamodel .mapping .internal .SingleAttributeIdentifierMapping ;
1717import org .hibernate .type .BasicType ;
18- import org .hibernate .type .SqlTypes ;
1918import org .hibernate .type .descriptor .WrapperOptions ;
2019import org .hibernate .type .descriptor .java .BasicPluralJavaType ;
2120import org .hibernate .type .descriptor .java .JavaType ;
2726
2827import java .io .IOException ;
2928import java .lang .reflect .Array ;
29+ import java .util .Collection ;
3030
3131import static org .hibernate .type .descriptor .jdbc .StructHelper .getSubPart ;
3232
@@ -37,7 +37,8 @@ public class JsonGeneratingVisitor {
3737
3838 public static final JsonGeneratingVisitor INSTANCE = new JsonGeneratingVisitor ();
3939
40- protected JsonGeneratingVisitor () {}
40+ protected JsonGeneratingVisitor () {
41+ }
4142
4243 /**
4344 * Serializes an array of values into JSON object/array
@@ -56,40 +57,82 @@ public void visitArray(JavaType<?> elementJavaType, JdbcType elementJdbcType, Ob
5657 }
5758
5859 if ( elementJdbcType instanceof JsonJdbcType jsonElementJdbcType ) {
59- final EmbeddableMappingType embeddableMappingType = jsonElementJdbcType .getEmbeddableMappingType ();
60- for ( Object value : values ) {
60+ visitPluralAggregateValues ( jsonElementJdbcType , values , options , writer );
61+ }
62+ else {
63+ assert !(elementJdbcType instanceof AggregateJdbcType );
64+ visitBasicPluralValues ( elementJavaType , elementJdbcType , values , options , writer );
65+ }
66+ writer .endArray ();
67+ }
68+
69+ private void visitPluralAggregateValues (
70+ AggregateJdbcType elementJdbcType ,
71+ Object values ,
72+ WrapperOptions options ,
73+ JsonDocumentWriter writer ) {
74+ final EmbeddableMappingType embeddableMappingType = elementJdbcType .getEmbeddableMappingType ();
75+ if ( values .getClass ().isArray () ) {
76+ final var length = Array .getLength ( values );
77+ for ( int j = 0 ; j < length ; j ++ ) {
78+ try {
79+ visit ( embeddableMappingType , Array .get ( values , j ), options , writer );
80+ }
81+ catch (IOException e ) {
82+ throw new IllegalArgumentException ( "Could not serialize array element" , e );
83+ }
84+ }
85+ }
86+ else if ( values instanceof Collection <?> collection ) {
87+ for ( final var item : collection ) {
6188 try {
62- visit ( embeddableMappingType , value , options , writer );
89+ visit ( embeddableMappingType , item , options , writer );
6390 }
6491 catch (IOException e ) {
65- throw new IllegalArgumentException ( "Could not serialize JSON array value " , e );
92+ throw new IllegalArgumentException ( "Could not serialize array element " , e );
6693 }
6794 }
6895 }
6996 else {
70- assert !(elementJdbcType instanceof AggregateJdbcType );
71- for ( Object value : values ) {
72- if ( value == null ) {
97+ throw new IllegalArgumentException (
98+ "Expected array or collection value, but got: " + values .getClass ().getName ()
99+ );
100+ }
101+ }
102+
103+ private void visitBasicPluralValues (
104+ JavaType <?> elementJavaType ,
105+ JdbcType elementJdbcType ,
106+ Object values ,
107+ WrapperOptions options ,
108+ JsonDocumentWriter writer ) {
109+ if ( values .getClass ().isArray () ) {
110+ final var length = Array .getLength ( values );
111+ for ( int j = 0 ; j < length ; j ++ ) {
112+ final var item = Array .get ( values , j );
113+ if ( item == null ) {
73114 writer .nullValue ();
74115 }
75116 else {
76- writer .serializeJsonValue ( value , ( JavaType <?>) elementJavaType , elementJdbcType , options );
117+ writer .serializeJsonValue ( item , elementJavaType , elementJdbcType , options );
77118 }
78119 }
79120 }
80-
81- writer .endArray ();
82- }
83-
84- /**
85- * Checks that a <code>JDBCType</code> is assignable to an array
86- *
87- * @param type the jdbc type
88- * @return <code>true</code> if types is of array kind <code>false</code> otherwise.
89- */
90- private static boolean isArrayType (JdbcType type ) {
91- return (type .getDefaultSqlTypeCode () == SqlTypes .ARRAY ||
92- type .getDefaultSqlTypeCode () == SqlTypes .JSON_ARRAY );
121+ else if ( values instanceof Collection <?> collection ) {
122+ for ( final var item : collection ) {
123+ if ( item == null ) {
124+ writer .nullValue ();
125+ }
126+ else {
127+ writer .serializeJsonValue ( item , elementJavaType , elementJdbcType , options );
128+ }
129+ }
130+ }
131+ else {
132+ throw new IllegalArgumentException (
133+ "Expected array or collection value, but got: " + values .getClass ().getName ()
134+ );
135+ }
93136 }
94137
95138 public void visit (MappingType mappedType , Object value , WrapperOptions options , JsonDocumentWriter writer )
@@ -106,17 +149,26 @@ else if ( mappedType instanceof ManagedMappingType managedMappingType ) {
106149 serializeObject ( managedMappingType , value , options , writer );
107150 }
108151 else if ( mappedType instanceof BasicType <?> basicType ) {
109- if ( isArrayType ( basicType .getJdbcType () ) ) {
110- final int length = Array .getLength ( value );
152+ if ( basicType .getJdbcType () instanceof ArrayJdbcType arrayJdbcType ) {
153+ final var domainValue = basicType .convertToRelationalValue ( value );
154+ final var elementJdbcType = arrayJdbcType .getElementJdbcType ();
111155 writer .startArray ();
112- if ( length != 0 ) {
113- //noinspection unchecked
114- final JavaType <Object > elementJavaType = ((BasicPluralJavaType <Object >) basicType .getJdbcJavaType ()).getElementJavaType ();
115- final var elementJdbcType = ((ArrayJdbcType ) basicType .getJdbcType ()).getElementJdbcType ();
116- final Object domainArray = basicType .convertToRelationalValue ( value );
117- for ( int j = 0 ; j < length ; j ++ ) {
118- writer .serializeJsonValue ( Array .get ( domainArray , j ), elementJavaType , elementJdbcType , options );
119- }
156+ if ( elementJdbcType instanceof AggregateJdbcType aggregateJdbcType ) {
157+ visitPluralAggregateValues (
158+ aggregateJdbcType ,
159+ domainValue ,
160+ options ,
161+ writer
162+ );
163+ }
164+ else {
165+ visitBasicPluralValues (
166+ ((BasicPluralJavaType <?>) basicType .getJdbcJavaType ()).getElementJavaType (),
167+ elementJdbcType ,
168+ domainValue ,
169+ options ,
170+ writer
171+ );
120172 }
121173 writer .endArray ();
122174 }
0 commit comments