使用Golang结构体解析JSON字符串
使用Golang结构体解析JSON字符串 我正在尝试解析以下JSON字符串
{
"BookDocuments": ["{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0100000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651007,\"end_time\":1593930226.6520069,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0200000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651019,\"end_time\":1593930226.652019,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0300000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.65102,\"end_time\":1593930226.65202,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0400000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651021,\"end_time\":1593930226.652021,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0500000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651021,\"end_time\":1593930226.652021,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n"]
}
以下是我的结构体定义
type BookDocuments struct {
BookDocuments []Documents `json:"BookDocuments,omitempty"`
}
type Documents struct {
Book_id string `json:"Book_id,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
StartTime float64 `json:"start_time"`
EndTime float64 `json:"end_time,omitempty"`
Origin string `json:"origin,omitempty"`
Type string `json:"type,omitempty"`
Namespace string `json:"namespace,omitempty"`
library Info `json:"Info,omitempty"`
Annotations map[string]interface{} `json:"annotations,omitempty"`
}
type Info struct {
AccountID string `json:"account_id,omitempty"`
Operation string `json:"operation,omitempty"`
RemoteRegion string `json:"region,omitempty"`
RequestID string `json:"request_id,omitempty"`
QueueURL string `json:"queue_url,omitempty"`
TableName string `json:"table_name,omitempty"`
}
当我尝试反序列化时,我得到一个空数组,请问我该如何解决?
以下是我尝试运行的链接 https://play.golang.org/p/R97eh7tkgrq
更多关于使用Golang结构体解析JSON字符串的实战教程也可以访问 https://www.itying.com/category-94-b0.html
5 回复
你能给我一些示例来说明如何完成吗。
看起来 "BookDocuments" 包含的不是 JSON 对象,而是字符串。你可能需要实现 json.Unmarshaller 来解开这种字符串嵌套。
func main() {
fmt.Println("hello world")
}
你好,Shreyas!
这里是一个如何实现自定义 Unmarshaler 方法的示例:https://play.golang.org/p/otPTEGUzcaE
func main() {
bookDocuments := `{"BookDocuments": ["{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0100000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651007,\"end_time\":1593930226.6520069,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0200000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651019,\"end_time\":1593930226.652019,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0300000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.65102,\"end_time\":1593930226.65202,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0400000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651021,\"end_time\":1593930226.652021,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0500000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651021,\"end_time\":1593930226.652021,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n"]}`
var bd BookDocuments
if err := json.Unmarshal([]byte(bookDocuments), &bd); err != nil {
panic(err)
}
fmt.Println(bd)
}
func (bd *BookDocuments) UnmarshalJSON(b []byte) error {
d := map[string][]string{}
if err := json.Unmarshal(b, &d); err != nil {
return err
}
dd := []Documents{}
for _, bd := range d["BookDocuments"] {
d := Documents{}
if err := json.Unmarshal([]byte(bd), &d); err != nil {
panic(err)
}
dd = append(dd, d)
}
fmt.Println(dd)
fmt.Println(dd[0].Name)
return nil
}
我的例子并不是实现此功能的最佳方式,但希望能为你提供一个起点。
你的JSON中BookDocuments字段的值是一个字符串数组,每个字符串本身是一个JSON对象。你需要先解析外层的JSON,然后对每个字符串元素进行二次解析。
以下是修正后的代码:
package main
import (
"encoding/json"
"fmt"
)
type BookDocuments struct {
BookDocuments []string `json:"BookDocuments"`
}
type Document struct {
BookID string `json:"Book_id"`
ID string `json:"id"`
Name string `json:"name"`
StartTime float64 `json:"start_time"`
EndTime float64 `json:"end_time"`
Origin string `json:"origin"`
Type string `json:"type"`
Namespace string `json:"namespace"`
Library map[string]interface{} `json:"library"`
Annotations map[string]interface{} `json:"annotations"`
}
func main() {
jsonStr := `{
"BookDocuments": ["{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0100000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651007,\"end_time\":1593930226.6520069,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n", "{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0200000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651019,\"end_time\":1593930226.652019,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n"]
}`
var wrapper BookDocuments
err := json.Unmarshal([]byte(jsonStr), &wrapper)
if err != nil {
fmt.Printf("解析外层JSON失败: %v\n", err)
return
}
var documents []Document
for _, docStr := range wrapper.BookDocuments {
var doc Document
err := json.Unmarshal([]byte(docStr), &doc)
if err != nil {
fmt.Printf("解析文档失败: %v\n", err)
continue
}
documents = append(documents, doc)
}
fmt.Printf("成功解析 %d 个文档\n", len(documents))
for i, doc := range documents {
fmt.Printf("文档 %d: ID=%s, Name=%s\n", i+1, doc.ID, doc.Name)
}
}
如果你需要保持原来的结构体设计,可以使用json.RawMessage:
package main
import (
"encoding/json"
"fmt"
)
type BookDocuments struct {
BookDocuments []json.RawMessage `json:"BookDocuments"`
}
type Document struct {
BookID string `json:"Book_id"`
ID string `json:"id"`
Name string `json:"name"`
StartTime float64 `json:"start_time"`
EndTime float64 `json:"end_time"`
Origin string `json:"origin"`
Type string `json:"type"`
Namespace string `json:"namespace"`
Library map[string]interface{} `json:"library"`
Annotations map[string]interface{} `json:"annotations"`
}
func main() {
jsonStr := `{
"BookDocuments": ["{\"Book_id\":\"1-5f0171f2-000000000000000000000000\",\"id\":\"0100000000000000\",\"name\":\"words-generator-span\",\"start_time\":1593930226.651007,\"end_time\":1593930226.6520069,\"origin\":\"library::shelf::Author\",\"type\":\"sub\",\"namespace\":\"remote\",\"library\":{},\"annotations\":{\"words_generator_span_seq_num\":\"\",\"words_generator_Book_seq_num\":\"\"}}\n"]
}`
var wrapper BookDocuments
err := json.Unmarshal([]byte(jsonStr), &wrapper)
if err != nil {
fmt.Printf("解析失败: %v\n", err)
return
}
var documents []Document
for _, rawDoc := range wrapper.BookDocuments {
var doc Document
err := json.Unmarshal(rawDoc, &doc)
if err != nil {
fmt.Printf("解析文档失败: %v\n", err)
continue
}
documents = append(documents, doc)
}
fmt.Printf("成功解析 %d 个文档\n", len(documents))
}
主要问题:
BookDocuments字段的值是字符串数组,不是直接的对象数组- 结构体字段名需要与JSON标签完全匹配(注意大小写)
library字段在你的JSON中是空对象{},所以使用map[string]interface{}更合适

