Анализ нескольких объектов JSON в Go

# #go #unmarshalling

Вопрос:

Объекты, подобные приведенным ниже, могут быть довольно легко проанализированы с помощью encoding/json пакета.

 [ 
    {"something":"foo"},
    {"something-else":"bar"}
]
 

Проблема, с которой я сталкиваюсь, заключается в том, что с сервера возвращается несколько диктов, подобных этой :

 {"something":"foo"}
{"something-else":"bar"}
 

Это невозможно проанализировать с помощью приведенного ниже кода.

 correct_format := strings.Replace(string(resp_body), "}{", "},{", -1)
json_output := "["   correct_format   "]"
 

Я пытаюсь проанализировать общие данные обхода (см. Пример).

Как я могу это сделать?

Комментарии:

1. Это недопустимый json, поэтому сначала преобразуйте его в допустимый json, а затем проанализируйте его.

2. Этот JSON вообще невозможно разобрать, не говоря уже о том, чтобы легко, потому что он недействителен.

3. Json не является недействительным. На самом деле каждая строка содержит отдельный объект Json.

4. Обратите внимание, что документ по URL-адресу в вопросе содержит текстовый файл с разделителем строк JSON (т. Е. один документ JSON на строку).

5. Извините, по ошибке я отправил неправильный json

Ответ №1:

Предполагая, что ваш ввод действительно представляет собой серию действительных документов JSON, используйте json.Декодер для их декодирования:

 package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "strings"
)

var input = `
{"foo": "bar"}
{"foo": "baz"}
`

type Doc struct {
    Foo string
}

func main() {
    dec := json.NewDecoder(strings.NewReader(input))
    for {
        var doc Doc

        err := dec.Decode(amp;doc)
        if err == io.EOF {
            // all done
            break
        }
        if err != nil {
            log.Fatal(err)
        }

        fmt.Printf("% vn", doc)
    }
}
 

Детская площадка: https://play.golang.org/p/ANx8MoMC0yq

Если ваш ввод действительно соответствует тому, что вы указали в вопросе, это не JSON, и вам нужно написать свой собственный синтаксический анализатор.

Ответ №2:

Похоже, что каждая строка является собственным объектом json.

Вам может сойти с рук следующий код, который структурирует этот вывод в правильный json:

 package main

import (
    "fmt"
    "strings"
)

func main() {
    base := `{"trolo":"lolo"}
{"trolo2":"lolo2"}`

    delimited := strings.Replace(base, "n", ",", -1)

    final := "["   delimited   "]"
    fmt.Println(final)
}
 

Теперь вы должны иметь возможность пользоваться encoding/json библиотекой final .

Ответ №3:

Другим вариантом было бы проанализировать каждую входящую строку, строку за строкой, а затем добавить каждую в коллекцию в коде (т. Е. фрагмент). Для этого Go предоставляет сканер строк.

 yourCollection := []yourObject{}
scanner := bufio.NewScanner(YOUR_SOURCE)
for scanner.Scan() {
    obj, err := PARSE_JSON_INTO_yourObject(scanner.Text())
    if err != nil {
       // something
    }
    yourCollection = append(yourCollection, obj)
}
if err := scanner.Err(); err != nil {
    fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
 

Ответ №4:

Вы можете прочитать ndjson из файла строка за строкой и проанализировать его, а затем применить к нему логические операции. В приведенном ниже примере вместо чтения из файла я использовал массив строк JSON.

 import (
    "encoding/json"
    "fmt"
)

type NestedObject struct {
    D string
    E string
}

type OuterObject struct {
    A string
    B string
    C []NestedObject
}

func main() {

    myJsonString := []string{`{"A":"1","B":"2","C":[{"D":"100","E":"10"}]}`, `{"A":"11","B":"21","C":[{"D":"1001","E":"101"}]}`}
    for index, each := range myJsonString {
        fmt.Printf("Index value [%d] is [%v]n", index, each)
        var obj OuterObject
        json.Unmarshal([]byte(each), amp;obj)
        fmt.Printf("a: %v, b: %v, c: %v", obj.A, obj.B, obj.C)
        fmt.Println()
    }
}
 

Выход:

 Index value [0] is [{"A":"1","B":"2","C":[{"D":"100","E":"10"}]}]
a: 1, b: 2, c: [{100 10}]
Index value [1] is [{"A":"11","B":"21","C":[{"D":"1001","E":"101"}]}]
a: 11, b: 21, c: [{1001 101}]
 

Попробуйте это на игре golang