diff --git a/src/system/avro/V1MessageWriter.ts b/src/system/avro/V1MessageWriter.ts index 216ed25..5a30cd4 100644 --- a/src/system/avro/V1MessageWriter.ts +++ b/src/system/avro/V1MessageWriter.ts @@ -196,12 +196,12 @@ export class V1MessageWriter implements MessageWriter /** * Format the data for avro by add type specifications to the data * - * @param data - the data to format - * @param depth - recursion depth + * @param data - the data to format + * @param top_level - whether we are at the top level of the recursion * * @return the formatted data */ - setDataTypes( data: any, depth: number = 0 ): any + setDataTypes( data: any, top_level: boolean = true ): any { let data_formatted: any = {}; @@ -210,7 +210,7 @@ export class V1MessageWriter implements MessageWriter case 'object': if ( data == null ) { - data_formatted = null; + return null; } else if ( Array.isArray( data ) ) { @@ -218,10 +218,10 @@ export class V1MessageWriter implements MessageWriter data.forEach( ( datum ) => { - arr.push( this.setDataTypes( datum, depth + 1 ) ); + arr.push( this.setDataTypes( datum, false ) ); } ); - data_formatted = ( depth < 1 ) + data_formatted = ( top_level ) ? arr : { 'array': arr }; } @@ -231,36 +231,38 @@ export class V1MessageWriter implements MessageWriter Object.keys( data).forEach( ( key: string ) => { - const datum = this.setDataTypes( data[ key ], depth + 1 ); + // Do not include "private" keys + if ( key.startsWith( '__' ) ) + { + return; + } + + const datum = this.setDataTypes( data[ key ], false ); datum_formatted[ key ] = datum; } ); - data_formatted = ( depth < 1 ) + data_formatted = ( top_level ) ? datum_formatted : { 'map': datum_formatted }; } break; case 'boolean': - return { 'bucket': { 'map': { 'boolean': data } } }; + return { 'boolean': data }; case 'number': - return { 'bucket': { 'map': { 'double': data } } }; + return { 'double': data }; case 'string': - return { 'bucket': { 'map': { 'string': data } } }; + return { 'string': data }; case 'undefined': - return { 'bucket': { 'map': null } }; - } - - if ( depth > 1 ) - { - return { 'bucket': { 'map': data_formatted } }; + return null; } return data_formatted; } + } \ No newline at end of file diff --git a/src/system/avro/schema.avsc b/src/system/avro/schema.avsc index d19d881..63bbc7d 100644 --- a/src/system/avro/schema.avsc +++ b/src/system/avro/schema.avsc @@ -123,16 +123,50 @@ "type": "map", "values": [ "null", - "boolean", - "double", - "string", { "type": "array", - "items": "Data" - }, - { - "type": "map", - "values": "Data" + "items": [ + "null", + "boolean", + "double", + "string", + { + "type": "array", + "items": [ + "null", + "boolean", + "double", + "string", + { + "type": "array", + "items": [ + "null", + "boolean", + "double", + "string" + ] + } + ] + }, + { + "type": "map", + "values": [ + "null", + "boolean", + "double", + "string", + { + "type": "map", + "values": [ + "null", + "boolean", + "double", + "string" + ] + } + ] + } + ] } ] } diff --git a/test/system/V1MessageWriterTest.ts b/test/system/V1MessageWriterTest.ts index 95b7771..42bd302 100644 --- a/test/system/V1MessageWriterTest.ts +++ b/test/system/V1MessageWriterTest.ts @@ -95,59 +95,57 @@ describe( 'system.V1MessageWriter', () => { label: 'Null array', valid: true, - delta_data: { foo: { 'array': [ - { 'bucket': { 'map': null } } - ] } }, + delta_data: { foo: { 'array': [ null ] } }, }, { label: 'Boolean value', valid: true, delta_data: { foo: { 'array': [ - { 'bucket': { 'map': { 'boolean': true } } }, + { 'boolean': true }, ] } }, }, { label: 'Simple string', valid: true, delta_data: { foo: { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'string': 'baz' } } }, + { 'string': 'bar' }, + { 'string': 'baz' }, ] } }, }, { label: 'Simple int', valid: true, delta_data: { foo: { 'array': [ - { 'bucket': { 'map': { 'double': 123 } } }, + { 'double': 123 }, ] } }, }, { label: 'Nested array', valid: true, delta_data: { foo: { 'array': [ - { 'bucket': { 'map': { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - ] } } }, + { 'array': [ + { 'string': 'bar' }, + ] }, ] } }, }, { label: 'Array with nulls', valid: true, delta_data: { foo: { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'string': 'baz' } } }, - { 'bucket': { 'map': null } }, + { 'string': 'bar' }, + { 'string': 'baz' }, + null, ] } }, }, { label: 'Nested Array with mixed values', valid: true, delta_data: { foo: { 'array': [ - { 'bucket': { 'map': { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'double': 123321 } } }, - { 'bucket': { 'map': null } }, - ] } } } + { 'array': [ + { 'string': 'bar' }, + { 'double': 123321 }, + null, + ] } ] } }, }, { @@ -168,180 +166,14 @@ describe( 'system.V1MessageWriter', () => label: 'Map objects', valid: true, delta_data: { 'foo': { 'array': [ - { 'bucket': { 'map': { 'map': { 'bar': - { 'bucket': { 'map': { 'map': { 'baz': - { 'bucket': { 'map': { 'double': 1572903485000 } } } - } } } } - } } } } + { 'map': { + 'bar': { 'map': { + 'baz': { 'double': 1572903485000 }, + } } + } } ] } }, - }, - { - label: 'Arbitrary array/map depth', - valid: true, - delta_data: { - "a": { "array": [ - { "bucket": { "map": { "map": { - "b": { "bucket": { "map": { "array": [ - { "bucket": { "map": { - "string": "c" - } } }, - { "bucket": { "map": { "array": [ - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "d" - } } }, - { "bucket": { "map": { - "map": { - "e": { "bucket": { "map": { "string": "f" } } }, - "g": { "bucket": { "map": { "string": "h" } } }, - "i": { "bucket": { "map": { "string": "j" } } }, - "k": { "bucket": { "map": { "string": "l" } } }, - "m": { "bucket": { "map": { "string": "n" } } } - } - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "o" - } } }, - { "bucket": { "map": { - "map": { - "p": { "bucket": { "map": { - "string": "q" - } } }, - "r": { "bucket": { "map": { - "string": "s" - } } }, - "t": { "bucket": { "map": { - "string": "u" - } } } - } - } } }, - { "bucket": { "map": { "array": [] } } }, - { "bucket": { "map": null } } - ] - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "v" - } } }, - { "bucket": { "map": { - "map": { - "w": { "bucket": { "map": { "string": "x" } } }, - "y": { "bucket": { "map": { "string": "z" } } } - } - } } }, - { - "bucket": { - "map": { - "array": [ - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "aa" - } } }, - { "bucket": { "map": { - "map": { - "ab": { - "bucket": { - "map": { - "string": "ac" - } - } - }, - "ad": { - "bucket": { - "map": { - "string": "ae" - } - } - }, - "af": { - "bucket": { - "map": { - "string": "ag" - } - } - }, - "ah": { - "bucket": { - "map": { - "string": "ai" - } - } - } - } - } } }, - { "bucket": { "map": { - "array": [] - } } }, - { "bucket": { "map": null } } - ] - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "aj" - } } }, - { "bucket": { "map": { - "map": { - "ak": { - "bucket": { "map": { - "string": "al" - } } - }, - "am": { - "bucket": { "map": { - "string": "an" - } } - }, - "ao": { - "bucket": { "map": { - "string": "ap" - } } - } - } - } } }, - { "bucket": { "map": { - "array": [] - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "q" - } } } - ] - } } } - ] - } } } - ] - } - } - }, - { "bucket": { "map": { - "string": "" - } } } - ] - } } } - ] - } } }, - { "bucket": { "map": { - "string": "" - } } } - ] - } } } - ] } } }, - { "bucket": { "map": null } }, - { "bucket": { "map": { "boolean": false } } } - ] } } } - } } } } - ] } - }, - }, + } + ].forEach( ( { label, delta_data, valid, expected } ) => { it( label, () => @@ -408,7 +240,7 @@ describe( 'system.V1MessageWriter', () => label: 'Boolean Value', delta_data: { foo: [ true ] }, expected: { foo: { 'array': [ - { 'bucket': { 'map': { 'boolean': true } } }, + { 'boolean': true }, ] } }, }, { @@ -418,8 +250,8 @@ describe( 'system.V1MessageWriter', () => 'baz', ] }, expected: { foo: { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'string': 'baz' } } }, + { 'string': 'bar' }, + { 'string': 'baz' }, ] } }, }, { @@ -428,7 +260,7 @@ describe( 'system.V1MessageWriter', () => 123 ] }, expected: { foo: { 'array': [ - { 'bucket': { 'map': { 'double': 123 } } }, + { 'double': 123 }, ] } }, }, { @@ -440,10 +272,10 @@ describe( 'system.V1MessageWriter', () => ] ] }, expected: { foo: { 'array': [ - { 'bucket': { 'map': { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'string': 'baz' } } }, - ] } } }, + { 'array': [ + { 'string': 'bar' }, + { 'string': 'baz' }, + ] }, ] } }, }, { @@ -458,13 +290,13 @@ describe( 'system.V1MessageWriter', () => ], ] }, expected: { foo: { 'array': [ - { 'bucket': { 'map': { 'array': [ - { 'bucket': { 'map': { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'double': 123 } } }, - { 'bucket': { 'map': null } }, - ] } } }, - ] } } }, + { 'array': [ + { 'array': [ + { 'string': 'bar' }, + { 'double': 123 }, + null, + ] }, + ] }, ] } }, }, { @@ -475,13 +307,13 @@ describe( 'system.V1MessageWriter', () => null ] }, expected: { foo: { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'string': 'baz' } } }, - { 'bucket': { 'map': null } }, + { 'string': 'bar' }, + { 'string': 'baz' }, + null ] } }, }, { - label: 'Nested array with mixed values', + label: 'Nested Array with mixed values', delta_data: { foo: [ [ 'bar', @@ -490,15 +322,15 @@ describe( 'system.V1MessageWriter', () => ] ] }, expected: { foo: { 'array': [ - { 'bucket': { 'map': { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'double': 123321 } } }, - { 'bucket': { 'map': null } }, - ] } } } - ] } }, + { 'array': [ + { 'string': 'bar' }, + { 'double': 123321 }, + null, + ] }, + ] } }, }, { - label: 'Nested map with mixed values', + label: 'Nested Array with mixed values', delta_data: { foo: [ { 'bar': { @@ -510,256 +342,16 @@ describe( 'system.V1MessageWriter', () => }, ] }, expected: { 'foo': { 'array': [ - { 'bucket': { 'map': { 'map': { 'bar': - { 'bucket': { 'map': { 'map': { - 'wer': { 'bucket': { 'map': { - 'string': 'qaz' - } } }, - 'qwe': { 'bucket': { 'map': { - 'double': 1572903485000 - } } }, - 'asd': { 'bucket': { 'map': { - 'boolean': true - } } }, - 'zxc': { 'bucket': { 'map': null } } - } } } } - } } } } + { 'map': { + 'bar': { 'map': { + 'wer': { 'string': 'qaz' }, + 'qwe': { 'double': 1572903485000 }, + 'asd': { 'boolean': true }, + 'zxc': null, + } }, + } }, ] } }, }, - { - label: 'Arbitrary array/map depth', - delta_data: { - "a": [ - { - "b": [ - "c", - [ - [ - "d", - { - "e": "f", - "g": "h", - "i": "j", - "k": "l", - "m": "n" - }, - [ - [ - "o", - { - "p": "q", - "r": "s", - "t": "u" - }, - [], - null - ], - [ - "v", - { - "w": "x", - "y": "z" - }, - [ - [ - "aa", - { - "ab": "ac", - "ad": "ae", - "af": "ag", - "ah": "ai" - }, - [], - null - ], - [ - "aj", - { - "ak": "al", - "am": "an", - "ao": "ap" - }, - [], - [ - "q" - ] - ] - ], - "" - ] - ], - "" - ] - ], - null, - false - ], - } ], - }, - expected: { - "a": { "array": [ - { "bucket": { "map": { "map": { - "b": { "bucket": { "map": { "array": [ - { "bucket": { "map": { - "string": "c" - } } }, - { "bucket": { "map": { "array": [ - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "d" - } } }, - { "bucket": { "map": { - "map": { - "e": { "bucket": { "map": { "string": "f" } } }, - "g": { "bucket": { "map": { "string": "h" } } }, - "i": { "bucket": { "map": { "string": "j" } } }, - "k": { "bucket": { "map": { "string": "l" } } }, - "m": { "bucket": { "map": { "string": "n" } } } - } - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "o" - } } }, - { "bucket": { "map": { - "map": { - "p": { "bucket": { "map": { - "string": "q" - } } }, - "r": { "bucket": { "map": { - "string": "s" - } } }, - "t": { "bucket": { "map": { - "string": "u" - } } } - } - } } }, - { "bucket": { "map": { "array": [] } } }, - { "bucket": { "map": null } } - ] - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "v" - } } }, - { "bucket": { "map": { - "map": { - "w": { "bucket": { "map": { "string": "x" } } }, - "y": { "bucket": { "map": { "string": "z" } } } - } - } } }, - { - "bucket": { - "map": { - "array": [ - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "aa" - } } }, - { "bucket": { "map": { - "map": { - "ab": { - "bucket": { - "map": { - "string": "ac" - } - } - }, - "ad": { - "bucket": { - "map": { - "string": "ae" - } - } - }, - "af": { - "bucket": { - "map": { - "string": "ag" - } - } - }, - "ah": { - "bucket": { - "map": { - "string": "ai" - } - } - } - } - } } }, - { "bucket": { "map": { - "array": [] - } } }, - { "bucket": { "map": null } } - ] - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "aj" - } } }, - { "bucket": { "map": { - "map": { - "ak": { - "bucket": { "map": { - "string": "al" - } } - }, - "am": { - "bucket": { "map": { - "string": "an" - } } - }, - "ao": { - "bucket": { "map": { - "string": "ap" - } } - } - } - } } }, - { "bucket": { "map": { - "array": [] - } } }, - { "bucket": { "map": { - "array": [ - { "bucket": { "map": { - "string": "q" - } } } - ] - } } } - ] - } } } - ] - } - } - }, - { "bucket": { "map": { - "string": "" - } } } - ] - } } } - ] - } } }, - { "bucket": { "map": { - "string": "" - } } } - ] - } } } - ] } } }, - { "bucket": { "map": null } }, - { "bucket": { "map": { "boolean": false } } } - ] } } } - } } } } - ] } - }, - }, ].forEach( ( { label, delta_data, expected } ) => { it( label, () => @@ -832,8 +424,8 @@ describe( 'system.V1MessageWriter', () => Data: { bucket: { 'foo': { 'array': [ - { 'bucket': { 'map': { 'string': 'bar' } } }, - { 'bucket': { 'map': { 'string': 'baz' } } }, + { 'string': 'bar' }, + { 'string': 'baz' }, ] } }, },