Skip to content

Commit

Permalink
ready for v6 release
Browse files Browse the repository at this point in the history
  • Loading branch information
thedumbterminal committed Jan 24, 2023
1 parent 78063bb commit ba204a7
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 53 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## v6.0.0 (24/01/2023)

- Objects with no properties convert to JSON fields.
- Updated dependencies.

## v5.1.0 (11/08/2022)

- JSBQ CLI output now compatible with Google's bq CLI.
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsonschema-bigquery",
"version": "5.1.0",
"version": "6.0.0",
"description": "Convert JSON schema to Google BigQuery schema",
"main": "src/converter.js",
"scripts": {
Expand All @@ -24,7 +24,8 @@
"json",
"schema",
"google",
"bigquery"
"bigquery",
"convert"
],
"author": {
"name": "thedumbterminal",
Expand Down
15 changes: 7 additions & 8 deletions src/converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,9 @@ converter._array = (name, node) => {
}

converter._object = (name, node, mode) => {
let result
const hasProperties = _.isPlainObject(node.properties)
let result = {
fields: [],
}
let fieldType = 'RECORD'
try {
if (
Expand All @@ -179,16 +180,14 @@ converter._object = (name, node, mode) => {
node
)
}
if (!hasProperties) {
if (
!_.isPlainObject(node.properties) ||
Object.keys(node.properties).length === 0
) {
// Big Query can handle semi-structured data :
// https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-json#loading_semi-structured_json_data
fieldType = 'JSON'
return converter._scalar(name, fieldType, mode, node.description)
} else if (Object.keys(node.properties).length === 0) {
throw new SchemaError(
'Record fields must have one or more child fields',
node
)
}

result = converter._scalar(name, fieldType, mode, node.description)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"name": "street_address",
"type": "STRING",
"mode": "NULLABLE"
},
{
"name": "country",
"type": "JSON",
"mode": "NULLABLE"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"properties": {}
}
},
"additionalProperties": false
"additionalProperties": true
}
},
"additionalProperties": false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"schema": {
"fields": []
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"id": "http://yourdomain.com/schemas/myschema.json",
"description": "Complex example empty Object",
"type": "object",
"properties": {
"address": {
"type": "object",
"properties": {
"street_address": {
"type": "string"
},
"country": {
"type": "object",
"properties": {}
}
},
"additionalProperties": true
}
},
"additionalProperties": true
}
29 changes: 29 additions & 0 deletions test/integration/converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,33 @@ describe('converter integration', () => {
})
})
})

describe('continueOnError and preventAdditionalObjectProperties options', () => {
const sampleDir =
'./test/integration/continueOnErrorAndPreventAdditionalObjectProperties'
// eslint-disable-next-line mocha/no-setup-in-describe
const testDirs = fs.readdirSync(sampleDir)

// eslint-disable-next-line mocha/no-setup-in-describe
testDirs.forEach((dir) => {
describe(dir, () => {
let expected
let result

before(() => {
const inJson = require(`../../${sampleDir}/${dir}/input.json`)
expected = require(`../../${sampleDir}/${dir}/expected.json`)
const options = {
continueOnError: true,
preventAdditionalObjectProperties: true,
}
result = converter.run(inJson, options, 'p', 't')
})

it('converts to big query', () => {
assert.deepStrictEqual(result, expected)
})
})
})
})
})
65 changes: 23 additions & 42 deletions test/unit/converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,29 @@ describe('converter unit', () => {
})
})

context(
'with the "preventAdditionalObjectProperties" and "continueOnError" options',
() => {
let result

beforeEach(() => {
converter._options = {
preventAdditionalObjectProperties: true,
continueOnError: true,
}
const node = {
properties: {},
}
result = converter._object('test', node, 'NULLABLE')
})

it('skips the field', () => {
const expected = { fields: [] }
assert.deepStrictEqual(result, expected)
})
}
)

context('with no properties', () => {
it('converts to JSON when properties not defined', () => {
const expected = {
Expand All @@ -129,48 +152,6 @@ describe('converter unit', () => {
assert.deepStrictEqual(result, expected)
})
})

context('with zero properties', () => {
it('does not allow objects to have zero properties defined', () => {
const node = {
properties: {},
}
assert.throws(() => {
converter._object('test', node, 'NULLABLE')
}, /Record fields must have one or more child fields/)
})
})

context('with no properties continueOnError', () => {
beforeEach(() => {
converter._options = {
continueOnError: true,
}
})

it('does not allow objects to not have properties defined', () => {
assert.doesNotThrow(() => {
converter._object('test', {}, 'NULLABLE')
}, /No properties defined for object/)
})
})

context('with zero properties continueOnError', () => {
beforeEach(() => {
converter._options = {
continueOnError: true,
}
})

it('does not allow objects to have zero properties defined', () => {
const node = {
properties: {},
}
assert.doesNotThrow(() => {
converter._object('test', node, 'NULLABLE')
}, /Record fields must have one or more child fields/)
})
})
})

describe('run()', () => {
Expand Down

0 comments on commit ba204a7

Please sign in to comment.