Я пока не сравнивал два эти варианта по производительности, но в будущих задачах предпочту использовать первый вариант.
Вариант №1
На stackoverflow посоветовали взглянуть на библиотеку
https://godoc.org/launchpad.net/rjson#Unmarshal однако в ней не оказалось поддержки значений в одинарных ковычках.
В результате сделал форк и добавил поддержку одинарных ковычек.
package main
import (
"fmt"
"github.com/mantyr/rjson"
)
func main() {
data := []byte(`{
middle : {
src: "pictures/product/123.jpg",
place : '#preview-img', // Added support for JavaScript object parsing
title: "title"
}
}`)
var v struct {
Middle struct {
Src string
Place string
Title string
}
}
err := rjson.Unmarshal(data, &v)
fmt.Println(v) // print {{pictures/product/123.jpg #preview-img title}}
fmt.Println(err) // print <nil>
}
https://github.com/mantyr/rjson
Оригинальный пакет от автора тут:
https://github.com/rogpeppe/rjson
Если у вас есть пожелания по дополнению rjson - напишите мне или предложите pool request.
Вариант №2
Можно запустить VM
https://github.com/robertkrimen/otto и передав ей немного дополненный текст получить из неё нужное поле.
package main
import (
"testing"
"github.com/robertkrimen/otto"
)
func BenchmarkVMGet(b *testing.B) {
vm := otto.New()
b.ResetTimer()
for i := 0; i < b.N; i++ {
st := `
{
middle : {
src: 'pictures/product/middle/14906_middle.jpg',
place : '#preview-img',
title: '343880-090-slantsy-nike-benassi-just-do-it'
}
}
`
vm.Run(`
obj = `+st+`
src = obj.middle.src;
`)
src, err := vm.Get("src") // <-----
_ = src
_ = err
}
}
# go test -bench=".*" ottotest
testing: warning: no tests to run
PASS
BenchmarkVMGet 30000 58103 ns/op
ok ottotest 2.367s
Однако есть минусы:
- может прилететь произвольный кусок текста и выполнять его бездумно не правильно (вспомним eval в php)
- достаточно медленно
- используется очень большая библиотека - плохая зависимость
Плюсы:
- всё таки достаточно быстро
- можно не останавливать VM, а пушить туда через Run, но если пушить бесконечно остаётся вопрос - умрёт однажды или не умрёт - без хорошего знания внутренностей библиотеки сказать этого заранее нельзя
Я так же ищу другие варианты, чисто под задачу распарсить
object и не выполнять лишних операций.