@@ -3,6 +3,7 @@ package wu.seal.jsontokotlin
3
3
import org.junit.Before
4
4
import org.junit.Test
5
5
import wu.seal.jsontokotlin.test.TestConfig
6
+ import com.google.gson.annotations.SerializedName
6
7
7
8
class JsonSchemaTest {
8
9
@@ -61,4 +62,305 @@ class JsonSchemaTest {
61
62
val s = json.generateKotlinClassCode(" TestData" )
62
63
println (s)
63
64
}
65
+
66
+ @Test
67
+ fun testJsonSchemaWithDefs () {
68
+ val json = """ {
69
+ "${" $" } schema": "http://json-schema.org/draft-2020-12/schema",
70
+ "type": "object",
71
+ "title": "Payment",
72
+ "description": "A payment instruction with transaction details",
73
+ "properties": {
74
+ "paymentId": {
75
+ "type": "string",
76
+ "description": "Unique identifier for the payment"
77
+ },
78
+ "amount": {
79
+ "type": "number",
80
+ "description": "Payment amount"
81
+ },
82
+ "currency": {
83
+ "type": "string",
84
+ "description": "Payment currency code"
85
+ },
86
+ "transaction": {
87
+ "${" $" } ref": "#/${" $" } defs/Transaction"
88
+ }
89
+ },
90
+ "required": ["paymentId", "amount", "currency", "transaction"],
91
+ "${" $" } defs": {
92
+ "Transaction": {
93
+ "type": "object",
94
+ "properties": {
95
+ "transactionId": {
96
+ "type": "string",
97
+ "description": "Unique identifier for the transaction"
98
+ },
99
+ "status": {
100
+ "type": "string",
101
+ "enum": ["PENDING", "COMPLETED", "FAILED"],
102
+ "description": "Current status of the transaction"
103
+ },
104
+ "details": {
105
+ "${" $" } ref": "#/${" $" } defs/TransactionDetails"
106
+ }
107
+ },
108
+ "required": ["transactionId", "status"]
109
+ },
110
+ "TransactionDetails": {
111
+ "type": "object",
112
+ "properties": {
113
+ "createdAt": {
114
+ "type": "string",
115
+ "format": "date-time",
116
+ "description": "Transaction creation timestamp"
117
+ },
118
+ "updatedAt": {
119
+ "type": "string",
120
+ "format": "date-time",
121
+ "description": "Transaction last update timestamp"
122
+ },
123
+ "notes": {
124
+ "type": "string",
125
+ "description": "Additional notes about the transaction"
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }""" .trimIndent()
131
+
132
+ val expected = """ /**
133
+ * A payment instruction with transaction details
134
+ */
135
+ data class Payment(
136
+ /**
137
+ * Payment amount
138
+ */
139
+ @SerializedName("amount")
140
+ val amount: Double = 0.0,
141
+ /**
142
+ * Payment currency code
143
+ */
144
+ @SerializedName("currency")
145
+ val currency: String = "",
146
+ /**
147
+ * Unique identifier for the payment
148
+ */
149
+ @SerializedName("paymentId")
150
+ val paymentId: String = "",
151
+ @SerializedName("transaction")
152
+ val transaction: Transaction = Transaction()
153
+ ) {
154
+ data class Transaction(
155
+ @SerializedName("details")
156
+ val details: TransactionDetails = TransactionDetails(),
157
+ /**
158
+ * Current status of the transaction
159
+ */
160
+ @SerializedName("status")
161
+ val status: Status = Status(),
162
+ /**
163
+ * Unique identifier for the transaction
164
+ */
165
+ @SerializedName("transactionId")
166
+ val transactionId: String = ""
167
+ ) {
168
+ data class TransactionDetails(
169
+ /**
170
+ * Transaction creation timestamp
171
+ */
172
+ @SerializedName("createdAt")
173
+ val createdAt: java.time.OffsetDateTime = OffsetDateTime(),
174
+ /**
175
+ * Additional notes about the transaction
176
+ */
177
+ @SerializedName("notes")
178
+ val notes: String = "",
179
+ /**
180
+ * Transaction last update timestamp
181
+ */
182
+ @SerializedName("updatedAt")
183
+ val updatedAt: java.time.OffsetDateTime = OffsetDateTime()
184
+ )
185
+
186
+ /**
187
+ * Current status of the transaction
188
+ */
189
+ enum class Status(val value: String) {
190
+ PENDING("PENDING"),
191
+
192
+ COMPLETED("COMPLETED"),
193
+
194
+ FAILED("FAILED");
195
+ }
196
+ }
197
+ }""" .trimIndent()
198
+
199
+ val result = json.generateKotlinClassCode(" Payment" )
200
+ println (result)
201
+
202
+ // Use assertion to verify that the generated code matches the expected result
203
+ assert (result.trim() == expected) { " Generated code does not match expected output" }
204
+ }
205
+
206
+ @Test
207
+ fun testComplexJsonSchemaWithDefs () {
208
+ // This test simulates the case from the crash report involving #/$defs/CreditTransferTransaction39
209
+ val json = """ {
210
+ "${" $" } schema": "http://json-schema.org/draft-2020-12/schema",
211
+ "title": "PaymentInstruction",
212
+ "type": "object",
213
+ "properties": {
214
+ "msgId": {
215
+ "type": "string",
216
+ "description": "Point to point reference assigned by the instructing party to unambiguously identify the instruction"
217
+ },
218
+ "pmtInf": {
219
+ "type": "array",
220
+ "items": {
221
+ "${" $" } ref": "#/${" $" } defs/PaymentInformation"
222
+ }
223
+ }
224
+ },
225
+ "required": ["msgId", "pmtInf"],
226
+ "${" $" } defs": {
227
+ "PaymentInformation": {
228
+ "type": "object",
229
+ "properties": {
230
+ "pmtInfId": {
231
+ "type": "string",
232
+ "description": "Unique identification assigned by the sending party to unambiguously identify the payment information group"
233
+ },
234
+ "pmtMtd": {
235
+ "type": "string",
236
+ "description": "Specifies the means of payment that will be used to move the amount of money"
237
+ },
238
+ "cdtTrfTxInf": {
239
+ "type": "array",
240
+ "items": {
241
+ "${" $" } ref": "#/${" $" } defs/CreditTransferTransaction"
242
+ }
243
+ }
244
+ },
245
+ "required": ["pmtInfId", "pmtMtd"]
246
+ },
247
+ "CreditTransferTransaction": {
248
+ "type": "object",
249
+ "properties": {
250
+ "pmtId": {
251
+ "type": "object",
252
+ "properties": {
253
+ "endToEndId": {
254
+ "type": "string",
255
+ "description": "Unique identification assigned by the initiating party to unambiguously identify the transaction"
256
+ },
257
+ "txId": {
258
+ "type": "string",
259
+ "description": "Unique identification assigned by the first instructing agent to unambiguously identify the transaction"
260
+ }
261
+ },
262
+ "required": ["endToEndId"]
263
+ },
264
+ "amt": {
265
+ "${" $" } ref": "#/${" $" } defs/ActiveCurrencyAndAmount"
266
+ },
267
+ "cdtr": {
268
+ "${" $" } ref": "#/${" $" } defs/PartyIdentification"
269
+ },
270
+ "cdtrAcct": {
271
+ "${" $" } ref": "#/${" $" } defs/CashAccount"
272
+ }
273
+ },
274
+ "required": ["pmtId", "amt", "cdtr", "cdtrAcct"]
275
+ },
276
+ "ActiveCurrencyAndAmount": {
277
+ "type": "object",
278
+ "properties": {
279
+ "ccy": {
280
+ "type": "string",
281
+ "description": "Medium of exchange of value, such as USD or EUR"
282
+ },
283
+ "value": {
284
+ "type": "number",
285
+ "description": "Amount of money to be moved between the debtor and creditor"
286
+ }
287
+ },
288
+ "required": ["ccy", "value"]
289
+ },
290
+ "PartyIdentification": {
291
+ "type": "object",
292
+ "properties": {
293
+ "nm": {
294
+ "type": "string",
295
+ "description": "Name by which a party is known"
296
+ },
297
+ "ctctDtls": {
298
+ "type": "object",
299
+ "properties": {
300
+ "emailAdr": {
301
+ "type": "string",
302
+ "description": "Email address of the contact"
303
+ },
304
+ "phneNb": {
305
+ "type": "string",
306
+ "description": "Phone number of the contact"
307
+ }
308
+ }
309
+ }
310
+ },
311
+ "required": ["nm"]
312
+ },
313
+ "CashAccount": {
314
+ "type": "object",
315
+ "properties": {
316
+ "id": {
317
+ "type": "object",
318
+ "properties": {
319
+ "iban": {
320
+ "type": "string",
321
+ "description": "International Bank Account Number (IBAN)"
322
+ },
323
+ "othr": {
324
+ "type": "object",
325
+ "properties": {
326
+ "id": {
327
+ "type": "string",
328
+ "description": "Other account identification"
329
+ }
330
+ },
331
+ "required": ["id"]
332
+ }
333
+ }
334
+ },
335
+ "tp": {
336
+ "type": "object",
337
+ "properties": {
338
+ "cd": {
339
+ "type": "string",
340
+ "description": "Code specifying the nature or use of the account"
341
+ }
342
+ }
343
+ },
344
+ "ccy": {
345
+ "type": "string",
346
+ "description": "Identification of the currency in which the account is held"
347
+ }
348
+ },
349
+ "required": ["id"]
350
+ }
351
+ }
352
+ }""" .trimIndent()
353
+
354
+ // Execute the code generation - if it doesn't throw an exception, our fix works
355
+ val result = json.generateKotlinClassCode(" PaymentInstruction" )
356
+ println (result)
357
+
358
+ // Verify some basic expectations about the output
359
+ assert (result.contains(" data class PaymentInstruction" )) { " Missing PaymentInstruction class" }
360
+ assert (result.contains(" data class PaymentInformation" )) { " Missing PaymentInformation class" }
361
+ assert (result.contains(" data class CreditTransferTransaction" )) { " Missing CreditTransferTransaction class" }
362
+ assert (result.contains(" data class ActiveCurrencyAndAmount" )) { " Missing ActiveCurrencyAndAmount class" }
363
+ assert (result.contains(" data class PartyIdentification" )) { " Missing PartyIdentification class" }
364
+ assert (result.contains(" data class CashAccount" )) { " Missing CashAccount class" }
365
+ }
64
366
}
0 commit comments