Skip to content

Commit

Permalink
JSON output no longer quotes all values
Browse files Browse the repository at this point in the history
JSONInfosetInputter and Outputter were treating all values as strings.
This meant everyhing was quoted and was messier for the user to read.
In addition, not all json comes from dfdl, so it makes sense to support numbers.

The JSONInfosetInputter's getSimpleText function also throws a
NonTextFoundInSimpleContentException if a node in a nonscalar value, since
finding a nonscalar (such as an object or array) when your expecting a simple value
means the infoset does not match.

 DAFFODIL-2362

delete me
  • Loading branch information
parkera101093 committed Sep 30, 2024
1 parent aaf9f1c commit 6861528
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ class JsonInfosetInputter(input: java.io.InputStream) extends InfosetInputter {
jsp.getCurrentToken() match {
case JsonToken.START_OBJECT => if (objectDepth == 1) StartDocument else StartElement
case JsonToken.END_OBJECT => EndElement
case JsonToken.VALUE_STRING | JsonToken.VALUE_NULL => {
case JsonToken.VALUE_STRING |
JsonToken.VALUE_NUMBER_INT |
JsonToken.VALUE_NUMBER_FLOAT |
JsonToken.VALUE_TRUE |
JsonToken.VALUE_FALSE |
JsonToken.VALUE_NULL => {
// we don't want to start faking element end yet, but signify that
// after a call to next(), we will want to fake it
nextEventShouldBeFakeEnd = true
Expand Down Expand Up @@ -118,10 +123,11 @@ class JsonInfosetInputter(input: java.io.InputStream) extends InfosetInputter {
primType: NodeInfo.Kind,
runtimeProperties: java.util.Map[String, String]
): String = {
if (jsp.getCurrentToken() == JsonToken.VALUE_NULL) {
if (!jsp.getCurrentToken().isScalarValue()) {
throw new NonTextFoundInSimpleContentException("Unexpected array or object '" + getLocalName + "' on line " + jsp.getTokenLocation().getLineNr())

Check warning on line 127 in daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/JsonInfosetInputter.scala

View check run for this annotation

Codecov / codecov/patch

daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/infoset/JsonInfosetInputter.scala#L127

Added line #L127 was not covered by tests
} else if (jsp.getCurrentToken() == JsonToken.VALUE_NULL) {
null
} else {
Assert.invariant(jsp.getCurrentToken() == JsonToken.VALUE_STRING)
// this handles unescaping any escaped characters
jsp.getText()
}
Expand Down Expand Up @@ -172,7 +178,7 @@ class JsonInfosetInputter(input: java.io.InputStream) extends InfosetInputter {
objectDepth -= 1; exitNow = true

// start of a simple type or null
case JsonToken.VALUE_STRING | JsonToken.VALUE_NULL => exitNow = true
case token if token.isScalarValue() => exitNow = true

// skip field names, jackson makes these available via
// getCurrentName(), except for array elements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,40 @@ class JsonInfosetOutputter private (writer: java.io.BufferedWriter, pretty: Bool
} else {
simple.getText
}
writer.write('"')
writer.write(text)
writer.write('"')
if (needsQuote(simple)) {
writer.write('"')
writer.write(text)
writer.write('"')
} else {
writer.write(text)
}
} else {
writer.write("null")
}
}

private def needsQuote(simple: InfosetSimpleElement): Boolean = {
simple.metadata.dfdlType match {
case DFDLPrimType.String => true
case DFDLPrimType.HexBinary => true
case DFDLPrimType.AnyURI => true
case DFDLPrimType.DateTime => true
case DFDLPrimType.Date => true
case DFDLPrimType.Time => true

// json does not support inf/nan double/float so they must be quoted
case DFDLPrimType.Double => {
val d = simple.getDouble
d.isInfinite || d.isNaN
}
case DFDLPrimType.Float => {
val f = simple.getFloat.toDouble
f.isInfinite || f.isNaN
}
case _ => false
}
}

override def endSimple(se: InfosetSimpleElement): Unit = {
// nothing to do
}
Expand Down

0 comments on commit 6861528

Please sign in to comment.