哪种是处理大型json并替换特定值的最佳方法?

I have a big json (30mb) which contains "title" fields in different objects , structure of json is unknown.

Known only that json contains keys "title" and string value of this key must be translated into another.

{
    "data1" : {
        "title" : "alpha",
        "color" : "green"
    },
    "data2" : {
        "someInnerData1" : {
            "title" : "beta"
            "color" : "red"
        },
        "someInnerData2" : {
            "someArray" : [
            {
                "title" : "gamme",
                "color" : "orange"
            },
            {
                "title" : "delta",
                "color" : "purple"
            }
            ],
            "title" : "epsilon"
        }
    }
}

Replace example "alpha" -> "Α" "beta" -> "B" etc..

Which the best way achieve that in Golang , without decoding into struct ?

P.S. Json is received from network.

You can use a streaming JSON decoder like megajson:

// 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
    }
}

This should do the titleizing on the fly. The one case I can think of where it will have a problem is if you have a really really big string.

I would make a struct that implements the io.Reader interface, and use that reader as a translation ground: you can use it to get you JSON input chunk by chunk, and detect when you are on a key that need to be changed, so translate it on the fly.

Then, you just have to use a io.Copy to read the whole file into another.

See the text.transform package dependency graph for examples…