mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
Avoid spurious [] on JSON output in some cases (#1528)
* JSON empty vs `[]` handling [WIP] * unit-test mods
This commit is contained in:
parent
d0a1acecec
commit
f01bb92da7
20 changed files with 56 additions and 28 deletions
|
|
@ -17,6 +17,8 @@ import (
|
|||
type RecordReaderJSON struct {
|
||||
readerOptions *cli.TReaderOptions
|
||||
recordsPerBatch int64 // distinct from readerOptions.RecordsPerBatch for join/repl
|
||||
// XXX 1513
|
||||
sawBrackets bool
|
||||
}
|
||||
|
||||
func NewRecordReaderJSON(
|
||||
|
|
@ -65,6 +67,7 @@ func (reader *RecordReaderJSON) Read(
|
|||
}
|
||||
}
|
||||
}
|
||||
context.JSONHadBrackets = reader.sawBrackets
|
||||
readerChannel <- types.NewEndOfStreamMarkerList(&context)
|
||||
}
|
||||
|
||||
|
|
@ -137,6 +140,9 @@ func (reader *RecordReaderJSON) processHandle(
|
|||
}
|
||||
|
||||
} else if mlrval.IsArray() {
|
||||
|
||||
reader.sawBrackets = true
|
||||
|
||||
records := mlrval.GetArray()
|
||||
if records == nil {
|
||||
errorChannel <- fmt.Errorf("internal coding error detected in JSON record-reader")
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ func channelWriterHandleBatch(
|
|||
|
||||
if !recordAndContext.EndOfStream {
|
||||
record := recordAndContext.Record
|
||||
context := &recordAndContext.Context
|
||||
|
||||
// XXX more
|
||||
// XXX also make sure this results in exit 1 & goroutine cleanup
|
||||
|
|
@ -94,7 +95,7 @@ func channelWriterHandleBatch(
|
|||
}
|
||||
|
||||
if record != nil {
|
||||
err := recordWriter.Write(record, bufferedOutputStream, outputIsStdout)
|
||||
err := recordWriter.Write(record, context, bufferedOutputStream, outputIsStdout)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
|
||||
return true, true
|
||||
|
|
@ -115,7 +116,8 @@ func channelWriterHandleBatch(
|
|||
// queued up. For example, PPRINT needs to see all same-schema
|
||||
// records before printing any, since it needs to compute max width
|
||||
// down columns.
|
||||
err := recordWriter.Write(nil, bufferedOutputStream, outputIsStdout)
|
||||
context := &recordAndContext.Context
|
||||
err := recordWriter.Write(nil, context, bufferedOutputStream, outputIsStdout)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
|
||||
return true, true
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bufio"
|
||||
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
// IRecordWriter is the abstract interface for all record-writers. They are
|
||||
|
|
@ -18,6 +19,7 @@ import (
|
|||
type IRecordWriter interface {
|
||||
Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
context *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
type RecordWriterCSV struct {
|
||||
|
|
@ -41,6 +42,7 @@ func NewRecordWriterCSV(writerOptions *cli.TWriterOptions) (*RecordWriterCSV, er
|
|||
|
||||
func (writer *RecordWriterCSV) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/colorizer"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
type RecordWriterCSVLite struct {
|
||||
|
|
@ -27,6 +28,7 @@ func NewRecordWriterCSVLite(writerOptions *cli.TWriterOptions) (*RecordWriterCSV
|
|||
|
||||
func (writer *RecordWriterCSVLite) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/colorizer"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
type RecordWriterDKVP struct {
|
||||
|
|
@ -20,6 +21,7 @@ func NewRecordWriterDKVP(writerOptions *cli.TWriterOptions) (*RecordWriterDKVP,
|
|||
|
||||
func (writer *RecordWriterDKVP) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -17,7 +18,7 @@ type RecordWriterJSON struct {
|
|||
jvQuoteAll bool
|
||||
|
||||
// State:
|
||||
onFirst bool
|
||||
wroteAnyRecords bool
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -27,16 +28,17 @@ func NewRecordWriterJSON(writerOptions *cli.TWriterOptions) (*RecordWriterJSON,
|
|||
jsonFormatting = mlrval.JSON_MULTILINE
|
||||
}
|
||||
return &RecordWriterJSON{
|
||||
writerOptions: writerOptions,
|
||||
jsonFormatting: jsonFormatting,
|
||||
jvQuoteAll: writerOptions.JVQuoteAll,
|
||||
onFirst: true,
|
||||
writerOptions: writerOptions,
|
||||
jsonFormatting: jsonFormatting,
|
||||
jvQuoteAll: writerOptions.JVQuoteAll,
|
||||
wroteAnyRecords: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (writer *RecordWriterJSON) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
context *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
@ -45,9 +47,9 @@ func (writer *RecordWriterJSON) Write(
|
|||
}
|
||||
|
||||
if writer.writerOptions.WrapJSONOutputInOuterList {
|
||||
writer.writeWithListWrap(outrec, bufferedOutputStream, outputIsStdout)
|
||||
writer.writeWithListWrap(outrec, context, bufferedOutputStream, outputIsStdout)
|
||||
} else {
|
||||
writer.writeWithoutListWrap(outrec, bufferedOutputStream, outputIsStdout)
|
||||
writer.writeWithoutListWrap(outrec, context, bufferedOutputStream, outputIsStdout)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -55,11 +57,12 @@ func (writer *RecordWriterJSON) Write(
|
|||
// ----------------------------------------------------------------
|
||||
func (writer *RecordWriterJSON) writeWithListWrap(
|
||||
outrec *mlrval.Mlrmap,
|
||||
context *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) {
|
||||
if outrec != nil { // Not end of record stream
|
||||
if writer.onFirst {
|
||||
if !writer.wroteAnyRecords {
|
||||
bufferedOutputStream.WriteString("[\n")
|
||||
}
|
||||
|
||||
|
|
@ -71,25 +74,32 @@ func (writer *RecordWriterJSON) writeWithListWrap(
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !writer.onFirst {
|
||||
if writer.wroteAnyRecords {
|
||||
bufferedOutputStream.WriteString(",\n")
|
||||
}
|
||||
|
||||
bufferedOutputStream.WriteString(s)
|
||||
|
||||
writer.onFirst = false
|
||||
writer.wroteAnyRecords = true
|
||||
|
||||
} else { // End of record stream
|
||||
if writer.onFirst { // zero records in the entire output stream
|
||||
bufferedOutputStream.WriteString("[")
|
||||
|
||||
if !writer.wroteAnyRecords {
|
||||
if context.JSONHadBrackets {
|
||||
bufferedOutputStream.WriteString("[")
|
||||
bufferedOutputStream.WriteString("\n]\n")
|
||||
}
|
||||
} else {
|
||||
bufferedOutputStream.WriteString("\n]\n")
|
||||
}
|
||||
bufferedOutputStream.WriteString("\n]\n")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (writer *RecordWriterJSON) writeWithoutListWrap(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/colorizer"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
type RecordWriterMarkdown struct {
|
||||
|
|
@ -29,6 +30,7 @@ func NewRecordWriterMarkdown(writerOptions *cli.TWriterOptions) (*RecordWriterMa
|
|||
// ----------------------------------------------------------------
|
||||
func (writer *RecordWriterMarkdown) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
type RecordWriterNIDX struct {
|
||||
|
|
@ -19,6 +20,7 @@ func NewRecordWriterNIDX(writerOptions *cli.TWriterOptions) (*RecordWriterNIDX,
|
|||
|
||||
func (writer *RecordWriterNIDX) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/colorizer"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
type RecordWriterPPRINT struct {
|
||||
|
|
@ -35,6 +36,7 @@ func NewRecordWriterPPRINT(writerOptions *cli.TWriterOptions) (*RecordWriterPPRI
|
|||
// ----------------------------------------------------------------
|
||||
func (writer *RecordWriterPPRINT) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/johnkerl/miller/pkg/colorizer"
|
||||
"github.com/johnkerl/miller/pkg/lib"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
type RecordWriterTSV struct {
|
||||
|
|
@ -35,6 +36,7 @@ func NewRecordWriterTSV(writerOptions *cli.TWriterOptions) (*RecordWriterTSV, er
|
|||
|
||||
func (writer *RecordWriterTSV) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/johnkerl/miller/pkg/cli"
|
||||
"github.com/johnkerl/miller/pkg/colorizer"
|
||||
"github.com/johnkerl/miller/pkg/mlrval"
|
||||
"github.com/johnkerl/miller/pkg/types"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -43,6 +44,7 @@ func NewRecordWriterXTAB(writerOptions *cli.TWriterOptions) (*RecordWriterXTAB,
|
|||
|
||||
func (writer *RecordWriterXTAB) Write(
|
||||
outrec *mlrval.Mlrmap,
|
||||
_ *types.Context,
|
||||
bufferedOutputStream *bufio.Writer,
|
||||
outputIsStdout bool,
|
||||
) error {
|
||||
|
|
|
|||
|
|
@ -639,7 +639,8 @@ func writeRecord(repl *Repl, outrec *mlrval.Mlrmap) {
|
|||
outrec.Unflatten(repl.options.WriterOptions.FLATSEP)
|
||||
}
|
||||
}
|
||||
repl.recordWriter.Write(outrec, repl.bufferedRecordOutputStream, true /*outputIsStdout*/)
|
||||
// XXX TEMP
|
||||
repl.recordWriter.Write(outrec, nil, repl.bufferedRecordOutputStream, true /*outputIsStdout*/)
|
||||
repl.bufferedRecordOutputStream.Flush()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,9 @@ type Context struct {
|
|||
// NF int
|
||||
NR int64
|
||||
FNR int64
|
||||
|
||||
// XXX 1513
|
||||
JSONHadBrackets bool
|
||||
}
|
||||
|
||||
// TODO: comment: Remember command-line values to pass along to CST evaluators.
|
||||
|
|
|
|||
|
|
@ -60,5 +60,3 @@
|
|||
"zsgnt": "int"
|
||||
}
|
||||
]
|
||||
[
|
||||
]
|
||||
|
|
|
|||
|
|
@ -9,5 +9,3 @@ x
|
|||
8
|
||||
9
|
||||
10
|
||||
[
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,5 +2,3 @@
|
|||
["X200", "X20", "X2", "X100", "X10", "X1"]
|
||||
["X1", "X2", "X10", "X20", "X100", "X200"]
|
||||
["X200", "X100", "X20", "X10", "X2", "X1"]
|
||||
[
|
||||
]
|
||||
|
|
|
|||
|
|
@ -18,5 +18,3 @@
|
|||
"b": 2,
|
||||
"c": 1
|
||||
}
|
||||
[
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
[
|
||||
]
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue