@@ -169,6 +169,8 @@ function jsonToGo(json, typename, flatten = true)
169
169
)
170
170
}
171
171
172
+ const seenTypeNames = [ ] ;
173
+
172
174
if ( flatten && depth >= 2 )
173
175
{
174
176
const parentType = `type ${ parent } ` ;
@@ -190,7 +192,9 @@ function jsonToGo(json, typename, flatten = true)
190
192
{
191
193
const keyname = getOriginalName ( keys [ i ] ) ;
192
194
indenter ( innerTabs )
193
- const typename = format ( keyname )
195
+ const typename = uniqueTypeName ( format ( keyname ) , seenTypeNames )
196
+ seenTypeNames . push ( typename )
197
+
194
198
appender ( typename + " " ) ;
195
199
parent = typename
196
200
parseScope ( scope [ keys [ i ] ] , depth ) ;
@@ -213,7 +217,8 @@ function jsonToGo(json, typename, flatten = true)
213
217
{
214
218
const keyname = getOriginalName ( keys [ i ] ) ;
215
219
indent ( tabs ) ;
216
- const typename = format ( keyname ) ;
220
+ const typename = uniqueTypeName ( format ( keyname ) , seenTypeNames )
221
+ seenTypeNames . push ( typename )
217
222
append ( typename + " " ) ;
218
223
parent = typename
219
224
parseScope ( scope [ keys [ i ] ] , depth ) ;
@@ -253,9 +258,41 @@ function jsonToGo(json, typename, flatten = true)
253
258
stack [ stack . length - 1 ] += str ;
254
259
}
255
260
261
+ // Generate a unique name to avoid duplicate struct field names.
262
+ // This function appends a number at the end of the field name.
263
+ function uniqueTypeName ( name , seen ) {
264
+ if ( seen . indexOf ( name ) === - 1 ) {
265
+ return name ;
266
+ }
267
+
268
+ let i = 0 ;
269
+ while ( true ) {
270
+ let newName = name + i . toString ( ) ;
271
+ if ( seen . indexOf ( newName ) === - 1 ) {
272
+ return newName ;
273
+ }
274
+
275
+ i ++ ;
276
+ }
277
+ }
278
+
256
279
// Sanitizes and formats a string to make an appropriate identifier in Go
257
280
function format ( str )
258
281
{
282
+ str = formatNumber ( str ) ;
283
+
284
+ let sanitized = toProperCase ( str ) . replace ( / [ ^ a - z 0 - 9 ] / ig, "" )
285
+ if ( ! sanitized ) {
286
+ return "NAMING_FAILED" ;
287
+ }
288
+
289
+ // After sanitizing the remaining characters can start with a number.
290
+ // Run the sanitized string again trough formatNumber to make sure the identifier is Num[0-9] or Zero_... instead of 1.
291
+ return formatNumber ( sanitized )
292
+ }
293
+
294
+ // Adds a prefix to a number to make an appropriate identifier in Go
295
+ function formatNumber ( str ) {
259
296
if ( ! str )
260
297
return "" ;
261
298
else if ( str . match ( / ^ \d + $ / ) )
@@ -267,7 +304,8 @@ function jsonToGo(json, typename, flatten = true)
267
304
'8' : "Eight_" , '9' : "Nine_" } ;
268
305
str = numbers [ str . charAt ( 0 ) ] + str . substr ( 1 ) ;
269
306
}
270
- return toProperCase ( str ) . replace ( / [ ^ a - z 0 - 9 ] / ig, "" ) || "NAMING_FAILED" ;
307
+
308
+ return str ;
271
309
}
272
310
273
311
// Determines the most appropriate Go type
@@ -324,12 +362,12 @@ function jsonToGo(json, typename, flatten = true)
324
362
if ( str . match ( / ^ [ _ A - Z 0 - 9 ] + $ / ) ) {
325
363
str = str . toLowerCase ( ) ;
326
364
}
327
-
365
+
328
366
// https://github.com/golang/lint/blob/5614ed5bae6fb75893070bdc0996a68765fdd275/lint.go#L771-L810
329
367
const commonInitialisms = [
330
- "ACL" , "API" , "ASCII" , "CPU" , "CSS" , "DNS" , "EOF" , "GUID" , "HTML" , "HTTP" ,
331
- "HTTPS" , "ID" , "IP" , "JSON" , "LHS" , "QPS" , "RAM" , "RHS" , "RPC" , "SLA" ,
332
- "SMTP" , "SQL" , "SSH" , "TCP" , "TLS" , "TTL" , "UDP" , "UI" , "UID" , "UUID" ,
368
+ "ACL" , "API" , "ASCII" , "CPU" , "CSS" , "DNS" , "EOF" , "GUID" , "HTML" , "HTTP" ,
369
+ "HTTPS" , "ID" , "IP" , "JSON" , "LHS" , "QPS" , "RAM" , "RHS" , "RPC" , "SLA" ,
370
+ "SMTP" , "SQL" , "SSH" , "TCP" , "TLS" , "TTL" , "UDP" , "UI" , "UID" , "UUID" ,
333
371
"URI" , "URL" , "UTF8" , "VM" , "XML" , "XMPP" , "XSRF" , "XSS"
334
372
] ;
335
373
0 commit comments