使用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 回复

谢谢

更多关于使用Golang结构体解析JSON字符串的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你能给我一些示例来说明如何完成吗。

看起来 "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))
}

主要问题:

  1. BookDocuments字段的值是字符串数组,不是直接的对象数组
  2. 结构体字段名需要与JSON标签完全匹配(注意大小写)
  3. library字段在你的JSON中是空对象{},所以使用map[string]interface{}更合适
回到顶部