@@ -14,7 +14,7 @@ function jsonToGo(json, typename, flatten = true)
1414 let go = "" ;
1515 let tabs = 0 ;
1616
17- const seen = [ ] ;
17+ const seen = { } ;
1818 const stack = [ ] ;
1919 let accumulator = "" ;
2020 let innerTabs = 0 ;
@@ -84,14 +84,31 @@ function jsonToGo(json, typename, flatten = true)
8484 const keys = Object . keys ( scope [ i ] )
8585 for ( let k in keys )
8686 {
87- const keyname = keys [ k ] ;
87+ let keyname = keys [ k ] ;
8888 if ( ! ( keyname in allFields ) ) {
8989 allFields [ keyname ] = {
9090 value : scope [ i ] [ keyname ] ,
9191 count : 0
9292 }
9393 }
94+ else {
95+ const existingValue = allFields [ keyname ] . value ;
96+ const currentValue = scope [ i ] [ keyname ] ;
9497
98+ if ( compareObjects ( existingValue , currentValue ) ) {
99+ const comparisonResult = compareObjectKeys (
100+ Object . keys ( currentValue ) ,
101+ Object . keys ( existingValue )
102+ )
103+ if ( ! comparisonResult ) {
104+ keyname = `${ keyname } _${ uuidv4 ( ) } ` ;
105+ allFields [ keyname ] = {
106+ value : currentValue ,
107+ count : 0
108+ } ;
109+ }
110+ }
111+ }
95112 allFields [ keyname ] . count ++ ;
96113 }
97114 }
@@ -155,24 +172,30 @@ function jsonToGo(json, typename, flatten = true)
155172 if ( flatten && depth >= 2 )
156173 {
157174 const parentType = `type ${ parent } ` ;
158- if ( seen . includes ( parentType ) ) {
175+ const scopeKeys = formatScopeKeys ( Object . keys ( scope ) ) ;
176+
177+ // this can only handle two duplicate items
178+ // future improvement will handle the case where there could
179+ // three or more duplicate keys with different values
180+ if ( parent in seen && compareObjectKeys ( scopeKeys , seen [ parent ] ) ) {
159181 stack . pop ( ) ;
160182 return
161183 }
162- seen . push ( parentType ) ;
184+ seen [ parent ] = scopeKeys ;
185+
163186 appender ( `${ parentType } struct {\n` ) ;
164187 ++ innerTabs ;
165188 const keys = Object . keys ( scope ) ;
166189 for ( let i in keys )
167190 {
168- const keyname = keys [ i ] ;
191+ const keyname = getOriginalName ( keys [ i ] ) ;
169192 indenter ( innerTabs )
170193 const typename = format ( keyname )
171194 appender ( typename + " " ) ;
172195 parent = typename
173- parseScope ( scope [ keyname ] , depth ) ;
196+ parseScope ( scope [ keys [ i ] ] , depth ) ;
174197 appender ( ' `json:"' + keyname ) ;
175- if ( omitempty && omitempty [ keyname ] === true )
198+ if ( omitempty && omitempty [ keys [ i ] ] === true )
176199 {
177200 appender ( ',omitempty' ) ;
178201 }
@@ -188,15 +211,14 @@ function jsonToGo(json, typename, flatten = true)
188211 const keys = Object . keys ( scope ) ;
189212 for ( let i in keys )
190213 {
191- const keyname = keys [ i ] ;
214+ const keyname = getOriginalName ( keys [ i ] ) ;
192215 indent ( tabs ) ;
193216 const typename = format ( keyname ) ;
194217 append ( typename + " " ) ;
195218 parent = typename
196- parseScope ( scope [ keyname ] , depth ) ;
197-
219+ parseScope ( scope [ keys [ i ] ] , depth ) ;
198220 append ( ' `json:"' + keyname ) ;
199- if ( omitempty && omitempty [ keyname ] === true )
221+ if ( omitempty && omitempty [ keys [ i ] ] === true )
200222 {
201223 append ( ',omitempty' ) ;
202224 }
@@ -320,6 +342,58 @@ function jsonToGo(json, typename, flatten = true)
320342 return sep + frag ;
321343 } ) ;
322344 }
345+
346+ function uuidv4 ( ) {
347+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' . replace ( / [ x y ] / g, function ( c ) {
348+ var r = Math . random ( ) * 16 | 0 , v = c == 'x' ? r : ( r & 0x3 | 0x8 ) ;
349+ return v . toString ( 16 ) ;
350+ } ) ;
351+ }
352+
353+ function getOriginalName ( unique ) {
354+ const reLiteralUUID = / ^ [ 0 - 9 a - f ] { 8 } - [ 0 - 9 a - f ] { 4 } - [ 1 - 5 ] [ 0 - 9 a - f ] { 3 } - [ 8 9 a b ] [ 0 - 9 a - f ] { 3 } - [ 0 - 9 a - f ] { 12 } $ / i
355+ const uuidLength = 36 ;
356+
357+ if ( unique . length >= uuidLength ) {
358+ const tail = unique . substr ( - uuidLength ) ;
359+ if ( reLiteralUUID . test ( tail ) ) {
360+ return unique . slice ( 0 , - 1 * ( uuidLength + 1 ) )
361+ }
362+ }
363+ return unique
364+ }
365+
366+ function compareObjects ( objectA , objectB ) {
367+ const object = "[object Object]" ;
368+ return Object . prototype . toString . call ( objectA ) === object
369+ && Object . prototype . toString . call ( objectB ) === object ;
370+ }
371+
372+ function compareObjectKeys ( itemAKeys , itemBKeys ) {
373+ const lengthA = itemAKeys . length ;
374+ const lengthB = itemBKeys . length ;
375+
376+ // nothing to compare, probably identical
377+ if ( lengthA == 0 && lengthB == 0 )
378+ return true ;
379+
380+ // duh
381+ if ( lengthA != lengthB )
382+ return false ;
383+
384+ for ( let item of itemAKeys ) {
385+ if ( ! itemBKeys . includes ( item ) )
386+ return false ;
387+ }
388+ return true ;
389+ }
390+
391+ function formatScopeKeys ( keys ) {
392+ for ( let i in keys ) {
393+ keys [ i ] = format ( keys [ i ] ) ;
394+ }
395+ return keys
396+ }
323397}
324398
325399if ( typeof module != 'undefined' ) {
@@ -331,4 +405,4 @@ if (typeof module != 'undefined') {
331405 } else {
332406 module . exports = jsonToGo
333407 }
334- }
408+ }
0 commit comments