猿问

哪个是处理大 json 和替换特定值的最佳方法?

我有一个很大的 json (30mb),其中包含不同对象中的“标题”字段,json 的结构未知。


只知道 json 包含键“title”,这个键的字符串值必须转换成另一个。


{

    "data1" : {

        "title" : "alpha",

        "color" : "green"

    },

    "data2" : {

        "someInnerData1" : {

            "title" : "beta"

            "color" : "red"

        },

        "someInnerData2" : {

            "someArray" : [

            {

                "title" : "gamme",

                "color" : "orange"

            },

            {

                "title" : "delta",

                "color" : "purple"

            }

            ],

            "title" : "epsilon"

        }

    }

}

替换示例“alpha”->“Α”“beta”->“B”等。


在 Golang 中实现这一目标的最佳方法是什么,而无需解码为 struct ?


PS Json 从网络接收。


SMILET
浏览 185回答 2
2回答

人到中年有点甜

我会创建一个实现io.Reader接口的结构,并使用该读取器作为翻译基础:您可以使用它来逐块获取 JSON 输入,并检测您何时使用需要更改的键,因此将其翻译苍蝇。然后,您只需使用 aio.Copy将整个文件读入另一个文件。有关示例,请参阅text.transform包依赖关系图...

POPMUISE

您可以使用像megajson这样的流式 JSON 解码器:// Transform 'title' strings into Title casefunc TitleizeJSON(r io.Reader, w io.Writer) error {    buf := new(bytes.Buffer)    r = io.TeeReader(r, buf)    s := scanner.NewScanner(r)    var prevTok int    var prevPos int    wasTitle := false    titleField := []byte("title")    for {        // read the next json token        tok, data, err := s.Scan()        if err == io.EOF {            return nil        } else if err != nil {            return err        }        // calculate the position in the buffer        pos := s.Pos()        off := pos - prevPos        switch tok {        // if this is a string        case scanner.TSTRING:            // if the previous string before a : was 'title', then            // titlelize it            if prevTok == scanner.TCOLON && wasTitle {                // grab the first part of the buffer and skip                // the first ", the titleize the rest                data = buf.Bytes()[:off][1:]                copy(data, bytes.Title(data))                wasTitle = false            } else {                wasTitle = bytes.Equal(data, titleField)            }        }        // now send the data to the writer        data = buf.Bytes()        _, err = w.Write(data[:off])        if err != nil {            return err        }        // reset the buffer (so it doesn't grow forever)        nbuf := make([]byte, len(data)-off)        copy(nbuf, data[off:])        buf.Reset()        buf.Write(nbuf)        // for the next go-around        prevTok = tok        prevPos = pos    }}这应该可以即时进行标题化。我能想到的一个问题是,如果你有一个非常大的字符串。
随时随地看视频慕课网APP

相关分类

Go
我要回答