我有一个大json(30mb),其中包含不同对象中的“title”字段,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?
P.S。 Json是从网络收到的。
答案 0 :(得分:0)
我会创建一个实现io.Reader
接口的结构,并使用该读取器作为转换基础:您可以使用它来获取块的JSON输入块,并检测何时使用需要的键要改变,所以即时翻译。
然后,您只需使用io.Copy
将整个文件读入另一个文件。
请参阅text.transform包依赖关系图以获取示例...
答案 1 :(得分:0)
您可以使用像megajson这样的流式JSON解码器:
// Transform 'title' strings into Title case
func 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
}
}
这应该在飞行中进行标题化。我能想到的一个问题就是如果你有一个非常大的字符串。