Bidirectional conversion of JSON <==> XML seems off.
Given the following insert changeSet in JSON from the source:
{
"databaseChangeLog": [
{
"changeSet": {
"id": "datatypetest-2",
"author": "nvoxland",
"validCheckSums": ["ANY"],
"changes": [
{
"insert": {
"tableName": "dataTypeTest",
"columns": [
{
"column": {
"name": "id",
"valueNumeric": 1
}
},
{
"column": {
"name": "dateCol",
"valueDate": "2007-08-09"
}
},
{
"column": {
"name": "timeCol",
"valueDate": "13:14:15"
}
},
{
"column": {
"name": "dateTimeCol",
"valueDate": "2007-08-09T13:14:15"
}
},
{
"column": {
"name": "bigintcol",
"valueNumeric": 2
}
}
]
}
},
{
"insert": {
"tableName": "dataTypeTest",
"columns": [
{
"column": {
"name": "id",
"valueNumeric": 2
}
},
{
"column": {
"name": "dateCol",
"valueDate": "current_datetime"
}
},
{
"column": {
"name": "timeCol",
"valueComputed": "current_datetime"
}
},
{
"column": {
"name": "dateTimeCol",
"valueDate": "current_datetime"
}
},
{
"column": {
"name": "bigintcol",
"valueNumeric": 2
}
}
]
}
}
]
}
}
]
}
When converted to XML using a the JQuery json2xml converter (and others), turns into the following XML
<?xml version="1.0" encoding="utf-8"?>
ANY
datatypetest-2
nvoxland
dataTypeTest
1
id
dateCol
2007-08-09
timeCol
13:14:15
dateTimeCol
2007-08-09T13:14:15
2
bigintcol
dataTypeTest
2
id
dateCol
current_datetime
timeCol
current_datetime
dateTimeCol
current_datetime
2
bigintcol
And the same insert changeSet in XML from the source:
<?xml version="1.0" encoding="UTF-8"?>
ANY
When converted using the JQuery xml2json, produces the following JSON:
{
"databaseChangeLog": {
"changeSet": {
"author": "nvoxland",
"id": "datatypetest-2",
"validCheckSum": "ANY",
"insert": [
{
"tableName": "dataTypeTest",
"column": [
{
"name": "id",
"valueNumeric": "1"
},
{
"name": "dateCol",
"valueDate": "2007-08-09"
},
{
"name": "timeCol",
"valueDate": "13:14:15"
},
{
"name": "dateTimeCol",
"valueDate": "2007-08-09T13:14:15"
},
{
"name": "bigintcol",
"valueNumeric": "2"
}
]
},
{
"dbms": "!derby",
"tableName": "dataTypeTest",
"column": [
{
"name": "id",
"valueNumeric": "2"
},
{
"name": "dateCol",
"valueDate": "current_datetime"
},
{
"name": "timeCol",
"valueComputed": "current_datetime"
},
{
"name": "dateTimeCol",
"valueDate": "current_datetime"
},
{
"name": "bigintcol",
"valueNumeric": "2"
}
]
}
]
}
}
}
I’m confused by this apparent discrepancy. It seems to prevent automated conversions from one format to another, which seems like a natural option given the relative compatibility of JSON, XML and YAML. I recognize that there are well-known problems with these conversions, but those don’t seem to be what is at play here.
I’d love to understand the thinking on this - it looks to me that you implemented YAML and got JSON, rather than deriving from your original XML structure.
The idea is that the XML format isn’t the canonical format, it is just one implementation. There is an underlying object structure which JSON/YAML/XML/SQL etc. are converted to and those objects are the real format. Each changelog format can be as different as they want as long as they can construct a valid object structure.
I tried to keep the JSON/YAML and XML structures similar to make documentation easier but at the same time tried to have the json/yaml format make sense as json/yaml. If anything, the json/yaml formats are more in line with the object model than the XML is because there are places where the XML format should be different but we jump through hoops to maintain backward compatibility.
If you are looking for JSON <==> XML conversion, that is possible using the liquibase classes. The XMLChangeLogParser/JSONChangeLogParser classes can consume XML/JSON classes to create a DatabaseChangeLogObject which can then be passed to XMLChangeLogSerializer and JSONChangeLogSerializer to re-output it, even in a different format.
I agree that the JSON/YAML format could be a bit less verbose. That’s what happens when you still try to be fairly similar to XML I may create a tighter DSL style format at some point as well.
Using the changelog parser/serializer classes, you should be able to shift formats down the road if you ever need. Or you can mix and match when using the tags as well.
Do you have an example of the lack of multiline support in JSON that you are seeing?
Thanks for the thorough explanation. What you say makes complete sense to me - you started with XML, so it’s going to be the more mature and encumbered of the formats.
I am not a big fan of XML in general, but in this instance it has won out as my format of choice for some very specific reasons:
Schema validation - when creating the database changelogs, many IDE's will provide code assistance and validation per the XSD's. IIRC neither YAML or JSON have a schema specification.
While the YAML markup is better suited as a DSL, I use IntelliJ, and it doesn't support the Language Injection feature for YAML - which I find incredibly valuable when dealing embedded SQL (createView, createProcedure, etc).
The JSON format is just too verbose for me - requiring the repeated "column" tag when the JSON itself handle arrays of values is troublesome.
Most damning for JSON is its lack of multiline support.
The Formatted SQL doesn't have the auto-rollback functionality.
This all came to the fore because at this point I’ve cycled through changelogs in every one of the four formats, I started with JSON, found its rough edges and moved to YAML, and got bit by invalid syntax and realized the superior format, for now, is XML - however I can see a need to move back to YAML at some point in the future, and having the ability to translate back and forth would really help me do that.
It does give me comfort knowing that I could translate using the Object Model and the parser/serializer classes.
I am currently mixing and matching my formats using the tag.
Sorry for the imprecise language - I’m referring to the JSON spec which does not allow embedded control characters, and therefore requires that multi-line strings have escaped newlines.
Good point, that is a problem with JSON in general that I hadn’t really thought of. For multiline sql you can use the sqlFile tag even in JSON, but it is a pain.