33import com .fasterxml .jackson .annotation .JsonAutoDetect ;
44import com .fasterxml .jackson .annotation .PropertyAccessor ;
55import com .fasterxml .jackson .core .JsonProcessingException ;
6+ import com .fasterxml .jackson .databind .JsonNode ;
67import com .fasterxml .jackson .databind .ObjectMapper ;
78import com .fasterxml .jackson .databind .SerializationFeature ;
9+ import com .fasterxml .jackson .databind .node .ArrayNode ;
10+ import com .fasterxml .jackson .databind .node .ObjectNode ;
11+ import com .fasterxml .jackson .module .jsonSchema .JsonSchema ;
12+ import com .fasterxml .jackson .module .jsonSchema .JsonSchemaGenerator ;
813
14+ /**
15+ * Utility class for working with JSON mappings and generating JSON schemas.
16+ * Provides methods for serializing and deserializing Java objects to and from JSON.
17+ * It also includes functionality to generate JSON schema representations.
18+ */
919public class MappingUtilities {
1020
1121 /**
12- * Visibility settings are applied to allow the mapper to access and serialize/deserialize all fields, while ignoring getters, setters, and creators .
13- * The FAIL_ON_EMPTY_BEANS serialization feature is disabled, which prevents the mapper from throwing an exception when encountering empty beans ( objects without any properties) .
22+ * Utility class for handling JSON serialization and deserialization .
23+ * Configures an {@link ObjectMapper} for serializing and deserializing Java objects to and from JSON .
1424 */
1525 public static class Json {
26+
27+ // An ObjectMapper configured for JSON operations
1628 public static ObjectMapper mapper = new ObjectMapper ();
1729
1830 static {
31+ // Configure ObjectMapper settings
1932 mapper .setVisibility (PropertyAccessor .FIELD , JsonAutoDetect .Visibility .ANY );
2033 mapper .setVisibility (PropertyAccessor .GETTER , JsonAutoDetect .Visibility .NONE );
2134 mapper .setVisibility (PropertyAccessor .SETTER , JsonAutoDetect .Visibility .NONE );
@@ -26,11 +39,11 @@ public static class Json {
2639 }
2740
2841 /**
29- * Converts the given object into its JSON string representation in a pretty-printed format .
42+ * Converts the given object into a JSON string representation with pretty-print formatting .
3043 *
3144 * @param <T> The type of the object to be converted to JSON.
3245 * @param body The object to be converted to JSON.
33- * @return The JSON string representation of the given object in a pretty-printed format.
46+ * @return The JSON string representation of the given object in pretty-printed format.
3447 */
3548 public static <T > String getJsonStringFor (T body ) {
3649 return mapper .valueToTree (body ).toPrettyString ();
@@ -42,13 +55,14 @@ public static <T> String getJsonStringFor(T body) {
4255 * @param <T> The type of the object to be converted to JSON.
4356 * @param body The object to be converted to JSON.
4457 * @return The JSON string representation of the given object in a pretty-printed format.
58+ * @throws JsonProcessingException If a JSON processing error occurs.
4559 */
4660 public static <T > String getJsonString (T body ) throws JsonProcessingException {
4761 return mapper .writerWithDefaultPrettyPrinter ().writeValueAsString (body );
4862 }
4963
5064 /**
51- * Converts a Json string representation of an object into a Java object of the specified type.
65+ * Converts a JSON string representation of an object into a Java object of the specified type.
5266 *
5367 * @param <T> The type of the object.
5468 * @param jsonString The JSON string representation of the object.
@@ -59,5 +73,116 @@ public static <T> String getJsonString(T body) throws JsonProcessingException {
5973 public static <T > T fromJsonString (String jsonString , Class <T > model ) throws JsonProcessingException {
6074 return MappingUtilities .Json .mapper .readValue (jsonString , model );
6175 }
76+
77+ /**
78+ * Utility class for generating JSON schema representations.
79+ */
80+ public static class Schema {
81+
82+ /**
83+ * Recursively sets the ID of all nested JSON schemas to null.
84+ * This method traverses through object schemas and array schemas, setting their ID properties to null.
85+ *
86+ * @param schema The root JsonSchema object to be processed.
87+ /**
88+ * Recursively sets the ID of all nested JSON schemas to null.
89+ * This method traverses through object schemas and array schemas, setting their ID properties to null.
90+ *
91+ * @param schema The root JsonSchema object to be processed.
92+ * @return The input JsonSchema with all nested schemas' IDs set to null.
93+ */
94+ public static JsonSchema setIdNull (JsonSchema schema ) {
95+ if (schema .isObjectSchema ()) {
96+ for (String propertyKey : schema .asObjectSchema ().getProperties ().keySet ()) {
97+ JsonSchema childSchema = schema .asObjectSchema ().getProperties ().get (propertyKey );
98+ if (childSchema .isObjectSchema ())
99+ setIdNull (childSchema );
100+
101+ if (childSchema .isArraySchema ())
102+ setIdNull (childSchema .asArraySchema ().getItems ().asSingleItems ().getSchema ());
103+
104+ schema .setId (null );
105+ schema .set$ref (null );
106+ }
107+ }
108+ return schema ;
109+ }
110+
111+ /**
112+ * Generates a JSON schema for the given class, with the option to specify required fields.
113+ * This method uses the Jackson library to generate the schema and customize it based on the provided required fields.
114+ * It sets the ID of the schema and its nested schemas to null and adds the required fields to the schema's "required" property.
115+ *
116+ * @param clazz The class for which the JSON schema should be generated.
117+ * @param requiredFields A varargs array of field names that should be marked as "required" in the schema.
118+ * @return A JsonNode representing the generated schema, or null if an exception occurs during generation.
119+ */
120+ public static JsonNode getJsonNodeFor (Class <?> clazz , String ... requiredFields ) {
121+ JsonSchema schema = generateSchema (clazz );
122+ assert schema != null ;
123+ schema .setId (null );
124+ return addRequiredFields (schema , requiredFields );
125+ }
126+
127+ /**
128+ * Generates a JSON schema for the given class, with the option to specify required fields.
129+ * This method uses the Jackson library to generate the schema.
130+ * It sets the ID of the schema and its nested schemas to null.
131+ *
132+ * @param clazz The class for which the JSON schema should be generated.
133+ * @return A JsonNode representing the generated schema, or null if an exception occurs during generation.
134+ */
135+ public static JsonNode getJsonNodeFor (Class <?> clazz ) {
136+ JsonSchema schema = generateSchema (clazz );
137+ assert schema != null ;
138+ schema .setId (null );
139+ return mapper .valueToTree (schema );
140+ }
141+
142+ /**
143+ * Generates a JSON schema for the given class, with the option to specify required fields.
144+ * This method uses the Jackson library to generate the schema and customize it based on the provided required fields.
145+ * It sets the ID of the schema and its nested schemas to null and adds the required fields to the schema's "required" property.
146+ *
147+ * @param clazz The class for which the JSON schema should be generated.
148+ * @return A JsonNode representing the generated schema, or null if an exception occurs during generation.
149+ */
150+ public static JsonSchema generateSchema (Class <?> clazz ) {
151+ try {
152+ JsonSchemaGenerator schemaGen = new JsonSchemaGenerator (new ObjectMapper ());
153+ return setIdNull (schemaGen .generateSchema (clazz ));
154+ } catch (Exception e ) {
155+ e .printStackTrace ();
156+ return null ;
157+ }
158+ }
159+
160+ /**
161+ * Adds the specified required fields to the "required" property of a JSON schema.
162+ * This method adds each field name from the provided array to the "required" property of the schema.
163+ *
164+ * @param schema The JSON schema to modify.
165+ * @param requiredFields An array of field names that should be marked as required in the schema.
166+ * @return
167+ */
168+ private static JsonNode addRequiredFields (JsonSchema schema , String [] requiredFields ) {
169+ JsonNode schemaNode = mapper .valueToTree (schema );
170+
171+ if (!(schemaNode instanceof ObjectNode root )) {
172+ throw new IllegalArgumentException ("Schema must be an ObjectNode" );
173+ }
174+
175+ ArrayNode required = root .withArray ("required" );
176+
177+ for (String fieldName : requiredFields ) {
178+ required .add (fieldName );
179+ }
180+
181+ // Convert the modified JsonNode back to JsonSchema
182+ return mapper .valueToTree (root );
183+ }
184+
185+ }
62186 }
63187}
188+
0 commit comments