【问题标题】:golang yaml support for jsonlinesgolang yaml 对 jsonlines 的支持
【发布时间】:2019-07-15 12:48:08
【问题描述】:

我一直在尝试让 go yaml 包解析带有 jsonlines 条目的文件。

下面是一个简单的示例,其中包含三个要解析的数据选项。

  • 选项一是一个多文档 yaml 示例。两个文档都可以解析。

  • 选项二是两个 jsonline 示例。第一行解析没问题,但是第二行就漏掉了。

  • 选项三是两个 jsonline 示例,但我在两者之间放置了 yaml 文档分隔符,以强制解决问题。这两个都可以解析。

通过阅读 yaml 和 json 规范,我相信第二个选项,多个 jsonlines,应该由 yaml 解析器处理。

我的问题是:

  • YAML 解析器应该处理 jsonlines 吗?
  • 我是否正确使用了 go yaml 包?

package main

import (
    "bytes"
    "fmt"
    "reflect"
    "strings"

    "gopkg.in/yaml.v2"
)

var testData = []string{
    `
---
option_one_first_yaml_doc: ok_here
---
option_one_second_yaml_doc: ok_here
`,
    `
{option_two_first_jsonl: ok_here}
{option_two_second_jsonl: missing}
`,
    `
---
{option_three_first_jsonl: ok_here}
---
{option_three_second_jsonl: ok_here}
`}

func printVal(v interface{}, depth int) {
    typ := reflect.TypeOf(v)
    if typ == nil {
        fmt.Printf(" %v\n", "<null>")
    } else if typ.Kind() == reflect.Int || typ.Kind() == reflect.String {
        fmt.Printf("%s%v\n", strings.Repeat(" ", depth), v)
    } else if typ.Kind() == reflect.Slice {
        fmt.Printf("\n")
        printSlice(v.([]interface{}), depth+1)
    } else if typ.Kind() == reflect.Map {
        fmt.Printf("\n")
        printMap(v.(map[interface{}]interface{}), depth+1)
    }
}

func printMap(m map[interface{}]interface{}, depth int) {
    for k, v := range m {
        fmt.Printf("%sKey: %s Value(s):", strings.Repeat(" ", depth), k.(string))
        printVal(v, depth+1)
    }
}

func printSlice(slc []interface{}, depth int) {
    for _, v := range slc {
        printVal(v, depth+1)
    }
}

func main() {

    m := make(map[interface{}]interface{})

    for _, data := range testData {

        yamlData := bytes.NewReader([]byte(data))
        decoder := yaml.NewDecoder(yamlData)

        for decoder.Decode(&m) == nil {
            printMap(m, 0)
            m = make(map[interface{}]interface{})

        }
    }
}

【问题讨论】:

  • YAML 规范的哪一部分让你认为支持 JSONL?
  • @Volker "8.2.3 Block Nodes",在 "9.1.3 Bare Documents" 内,但我不确定,因此提出了问题。 :)
  • 8.2.3 只会给你一个块节点,但不会解析 JSON。我很困惑。

标签: json go yaml jsonlines


【解决方案1】:

jsonlines 是换行符分隔的 JSON。这意味着单行是 JSON,但不是多行,当然也不是多行的整个文件。

您需要一次读取一行输入的 jsonlines,并且您应该能够使用 go yaml 处理这些行,因为 YAML 是 JSON 的超集。

由于您的测试中似乎也有 YAML 结束指示符 (---) 行,因此您 也需要处理这些。

【讨论】:

  • 使用 yaml 解码,这应该处理流,因此处理 (---) 或 (...) 终止符,对吗?它似乎适用于第一个和第二个例子。所以我不需要像使用 Unmarshall 那样处理这些问题,是正确的,还是我遗漏了什么?
  • 大多数 YAML 解析器期望在文档中(即在结束指示符之间)行有 valid YAML。如果有多个 jsonlines,则它不再是有效的 YAML 文件。你是如何创建这些多文档 YAML 类文件的。
  • 正如@Volker 指出的那样,我对关于 8.2.3 的规范感到困惑,所以我同意你答案的前两段,它回答了我的问题,但你的第三段指的是解析由 yaml.Decode 正确处理的 (---)。对吗?
  • 只有在 --- 之间你有有效的 YAML 时才是正确的。我再问你一次:你是如何创建这些 YAML 文件的?因为如果你自己这样做,就会有很多、更简单的解决方案。
  • YAML 是手动编辑的配置,目前为 48,描述用于人类基因分型的样品板的内容。它们位于单个文件中,并且可以正确解析,无需使用我发布的代码进行任何额外处理。 jsonlines 是使用 python (jsonlines package) 生成的,目前有 4608 个分布在 113 个文件中,并且还在增长。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 2017-08-13
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 2018-05-09
相关资源
最近更新 更多