从未编组的数据准备一个 json 对象
Prepare a json object from unmarshaled data
我有 json 这样的数据:
json: {"opt1":200,"opt3":"1","opt4":"13","opt5":null,"products":[{"product_id":1,"price":100,"variant_id":100},{"product_id":1,"price":100,"variant_id":null}]}
我使用
构建了它
type Products struct {
Product_id int
Price json.Number
Variant_id int
}
type Pdata struct {
Products []Products `json:"products"`
}
然后我用unmarshal
jsonb := []byte(jsonVal)
var data Pdata
err := json.Unmarshal(jsonb, &data)
if err != nil {
fmt.Println(err)
return
}
并得到类似
的输出
{[{1 100 100} {2 100 0}]}
现在我需要将该数据转换成这样的 json 对象
{"purchased_products": [{"product_id": 1,"price": 1200,"variation_id": 100},{"product_id": 2,"price": 100,"variation_id": null}]}
之后,我需要将它分配给“json”
var d = map[string]string{
"json": jsonVal,
"created_at": time.Now().Format("2006-01-02 15:04:05"),
"updated_at": time.Now().Format("2006-01-02 15:04:05"),
}
我该怎么做?
如下创建类型(例如:PurchasedProducts)。
type PurchasedProducts struct {
Products []Products `json:"purchased_products"`
}
并初始化一个 PurchasedProducts 类型变量,并将您未编组的产品分配给 Purchased 产品,如下所示。
pProducts := PurchasedProducts{Products: data.Products}
jsonByte, err := json.Marshal(pProducts)
if err != nil {
fmt.Println(err)
return
}
并将 []byte
数组转换为字符串并将其分配给如下地图。
var d = map[string]string{
"json": string(jsonByte),
"created_at": time.Now().Format("2006-01-02 15:04:05"),
"updated_at": time.Now().Format("2006-01-02 15:04:05"),
}
您可以 运行 并查看完整代码 here。
给你。
假设是:
- Product 是一个可能更复杂的模型,因此它有专用的结构。因此,从 Product 到 OutputProduct 的转换可以单独进行单元测试。
- 它是一次性使用的应用程序,而不是公开 API 的应用程序的一部分。否则它应该被适当地分成层并且输出应该被写成一个结构。
package main
import (
"encoding/json"
"log"
"os"
"time"
)
type (
Product struct {
ProductID int `json:"product_id"`
VariantID int `json:"variant_id"`
Price json.Number
}
Products []Product
OutputProduct struct {
ProductID int `json:"product_id"`
VariantID int `json:"variation_id"`
Price json.Number
}
)
func (p Product) ToOutputProduct() OutputProduct {
return OutputProduct{
ProductID: p.ProductID,
VariantID: p.VariantID,
Price: p.Price,
}
}
func (p Products) ToOutputProducts() []OutputProduct {
outputProducts := make([]OutputProduct, len(p))
for i := 0; i < len(p); i++ {
outputProducts[i] = p[i].ToOutputProduct()
}
return outputProducts
}
func main() {
var inputJSON = `{"opt1":200,"opt3":"1","opt4":"13","opt5":null,"products":[{"product_id":1,"price":100,"variant_id":100},{"product_id":1,"price":100,"variant_id":null}]}`
var parsedInput struct {
Products Products
}
if err := json.Unmarshal([]byte(inputJSON), &parsedInput); err != nil {
log.Fatal(err)
}
var output = map[string]interface{}{
"json": map[string][]OutputProduct{
"purchased_products": parsedInput.Products.ToOutputProducts(),
},
"created_at": time.Now().Format("2006-01-02 15:04:05"),
"updated_at": time.Now().Format("2006-01-02 15:04:05"),
}
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent(" ", " ")
if err := encoder.Encode(output); err != nil {
log.Fatal(err)
}
}
对于可为空的字段,您可以使用指针,例如,如果 variant_id
json 字段可以是整数或 json null
,并且您想要保留该信息,然后您可以将 Variant_id int
更改为 Variant_id *int
。
type Product struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id *int `json:"variant_id"`
}
要在 unmarshal 和 marshal 之间更改 json 字段名称,您可以声明第二个 Products
结构,其字段与原始结构相同,但结构标签定义了所需的字段名称,然后,如果在所有其他方面,结构都是等价的,您可以在它们之间进行转换。
type Product struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id int `json:"variant_id"`
}
type PurchasedProduct struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id int `json:"variation_id"` // here variant_id becomes variation_id
}
然后,如果 p
是 Product
类型,您可以像这样简单地将它转换为 PurchasedProduct
:
pp := PurchasedProduct(p)
要将转换卸载到封送处理过程,您可以让原始类型实现 json.Marshaler
接口并在那里进行转换。
func (p Product) MarshalJSON() ([]byte, error) {
type P struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id *int `json:"variation_id"`
}
return json.Marshal(P(p))
}
利用以上内容,您可以进行以下操作:
func main() {
// unmarshal
var pd Pdata
err := json.Unmarshal(data, &pd)
if err != nil {
panic(err)
}
// marshal
out, err := json.MarshalIndent(pd, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
只需再定义两个对第二个 JSON 对象建模的结构:
type Pdata2 struct {
PurchasedProducts []Product2
}
type Product2 struct {
Product_id int
Price json.Number
Variation_id *int // pointer to int
}
Variation_id
字段是 *int
类型,因为您所需的输出 JSON 显示 "variation_id": null
。如果将字段声明为简单 int
,它的零值将被编组为 0
.
然后使用之前的值初始化这些结构:
func main() {
data2 := Pdata2{
PurchasedProducts: make([]Product2, len(data.Products)),
}
for i, p := range data.Products {
data2.PurchasedProducts[i] = Product2{
Product_id: p.Product_id,
Price: p.Price,
Variation_id: nullableInt(p.Variant_id),
}
}
b, err := json.Marshal(data2)
if err != nil {
// ... handle error
}
var d = map[string]string{
"json": string(b),
// ...
}
fmt.Println(d)
}
func nullableInt(n int) *int {
if n == 0 {
return nil
}
return &n
}
根据评论的建议:
package main
import (
"encoding/json"
"log"
"time"
)
type Products struct {
Product_id int `json:"product_id"`
Price int `json:"price"`
Variant_id int `json:"variant_id"`
}
type ProductData struct {
Products []Products `json:"products"`
}
type Response struct {
Json json.RawMessage `json:"json"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
func main() {
productJson := `{
"opt1": 200,
"opt3": "1",
"opt4": "13",
"opt5": null,
"products": [
{ "product_id": 1, "price": 100, "variant_id": 100 },
{ "product_id": 1, "price": 100, "variant_id": null }
]
}`
productData := &ProductData{}
err := json.Unmarshal([]byte(productJson), &productData)
if err != nil {
panic(err)
}
b, err := json.Marshal(map[string]interface{}{"purchased_products": productData.Products})
if err != nil {
panic(err)
}
d := &Response{
Json: b,
CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
UpdatedAt: time.Now().Format("2006-01-02 15:04:05"),
}
out, err := json.Marshal(d)
if err != nil {
panic(err)
}
log.Println(string(out))
}
输出:
2009/11/10 23:00:00 {"json":{"purchased_products":[{"product_id":1,"price":100,"variant_id":100},{"product_id":1,"price":100,"variant_id":0}]},"created_at":"2009-11-10 23:00:00","updated_at":"2009-11-10 23:00:00"}
我有 json 这样的数据:
json: {"opt1":200,"opt3":"1","opt4":"13","opt5":null,"products":[{"product_id":1,"price":100,"variant_id":100},{"product_id":1,"price":100,"variant_id":null}]}
我使用
构建了它type Products struct {
Product_id int
Price json.Number
Variant_id int
}
type Pdata struct {
Products []Products `json:"products"`
}
然后我用unmarshal
jsonb := []byte(jsonVal)
var data Pdata
err := json.Unmarshal(jsonb, &data)
if err != nil {
fmt.Println(err)
return
}
并得到类似
的输出{[{1 100 100} {2 100 0}]}
现在我需要将该数据转换成这样的 json 对象
{"purchased_products": [{"product_id": 1,"price": 1200,"variation_id": 100},{"product_id": 2,"price": 100,"variation_id": null}]}
之后,我需要将它分配给“json”
var d = map[string]string{
"json": jsonVal,
"created_at": time.Now().Format("2006-01-02 15:04:05"),
"updated_at": time.Now().Format("2006-01-02 15:04:05"),
}
我该怎么做?
如下创建类型(例如:PurchasedProducts)。
type PurchasedProducts struct {
Products []Products `json:"purchased_products"`
}
并初始化一个 PurchasedProducts 类型变量,并将您未编组的产品分配给 Purchased 产品,如下所示。
pProducts := PurchasedProducts{Products: data.Products}
jsonByte, err := json.Marshal(pProducts)
if err != nil {
fmt.Println(err)
return
}
并将 []byte
数组转换为字符串并将其分配给如下地图。
var d = map[string]string{
"json": string(jsonByte),
"created_at": time.Now().Format("2006-01-02 15:04:05"),
"updated_at": time.Now().Format("2006-01-02 15:04:05"),
}
您可以 运行 并查看完整代码 here。
给你。 假设是:
- Product 是一个可能更复杂的模型,因此它有专用的结构。因此,从 Product 到 OutputProduct 的转换可以单独进行单元测试。
- 它是一次性使用的应用程序,而不是公开 API 的应用程序的一部分。否则它应该被适当地分成层并且输出应该被写成一个结构。
package main
import (
"encoding/json"
"log"
"os"
"time"
)
type (
Product struct {
ProductID int `json:"product_id"`
VariantID int `json:"variant_id"`
Price json.Number
}
Products []Product
OutputProduct struct {
ProductID int `json:"product_id"`
VariantID int `json:"variation_id"`
Price json.Number
}
)
func (p Product) ToOutputProduct() OutputProduct {
return OutputProduct{
ProductID: p.ProductID,
VariantID: p.VariantID,
Price: p.Price,
}
}
func (p Products) ToOutputProducts() []OutputProduct {
outputProducts := make([]OutputProduct, len(p))
for i := 0; i < len(p); i++ {
outputProducts[i] = p[i].ToOutputProduct()
}
return outputProducts
}
func main() {
var inputJSON = `{"opt1":200,"opt3":"1","opt4":"13","opt5":null,"products":[{"product_id":1,"price":100,"variant_id":100},{"product_id":1,"price":100,"variant_id":null}]}`
var parsedInput struct {
Products Products
}
if err := json.Unmarshal([]byte(inputJSON), &parsedInput); err != nil {
log.Fatal(err)
}
var output = map[string]interface{}{
"json": map[string][]OutputProduct{
"purchased_products": parsedInput.Products.ToOutputProducts(),
},
"created_at": time.Now().Format("2006-01-02 15:04:05"),
"updated_at": time.Now().Format("2006-01-02 15:04:05"),
}
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent(" ", " ")
if err := encoder.Encode(output); err != nil {
log.Fatal(err)
}
}
对于可为空的字段,您可以使用指针,例如,如果 variant_id
json 字段可以是整数或 json null
,并且您想要保留该信息,然后您可以将 Variant_id int
更改为 Variant_id *int
。
type Product struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id *int `json:"variant_id"`
}
要在 unmarshal 和 marshal 之间更改 json 字段名称,您可以声明第二个 Products
结构,其字段与原始结构相同,但结构标签定义了所需的字段名称,然后,如果在所有其他方面,结构都是等价的,您可以在它们之间进行转换。
type Product struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id int `json:"variant_id"`
}
type PurchasedProduct struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id int `json:"variation_id"` // here variant_id becomes variation_id
}
然后,如果 p
是 Product
类型,您可以像这样简单地将它转换为 PurchasedProduct
:
pp := PurchasedProduct(p)
要将转换卸载到封送处理过程,您可以让原始类型实现 json.Marshaler
接口并在那里进行转换。
func (p Product) MarshalJSON() ([]byte, error) {
type P struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id *int `json:"variation_id"`
}
return json.Marshal(P(p))
}
利用以上内容,您可以进行以下操作:
func main() {
// unmarshal
var pd Pdata
err := json.Unmarshal(data, &pd)
if err != nil {
panic(err)
}
// marshal
out, err := json.MarshalIndent(pd, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
只需再定义两个对第二个 JSON 对象建模的结构:
type Pdata2 struct {
PurchasedProducts []Product2
}
type Product2 struct {
Product_id int
Price json.Number
Variation_id *int // pointer to int
}
Variation_id
字段是 *int
类型,因为您所需的输出 JSON 显示 "variation_id": null
。如果将字段声明为简单 int
,它的零值将被编组为 0
.
然后使用之前的值初始化这些结构:
func main() {
data2 := Pdata2{
PurchasedProducts: make([]Product2, len(data.Products)),
}
for i, p := range data.Products {
data2.PurchasedProducts[i] = Product2{
Product_id: p.Product_id,
Price: p.Price,
Variation_id: nullableInt(p.Variant_id),
}
}
b, err := json.Marshal(data2)
if err != nil {
// ... handle error
}
var d = map[string]string{
"json": string(b),
// ...
}
fmt.Println(d)
}
func nullableInt(n int) *int {
if n == 0 {
return nil
}
return &n
}
根据评论的建议:
package main
import (
"encoding/json"
"log"
"time"
)
type Products struct {
Product_id int `json:"product_id"`
Price int `json:"price"`
Variant_id int `json:"variant_id"`
}
type ProductData struct {
Products []Products `json:"products"`
}
type Response struct {
Json json.RawMessage `json:"json"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
func main() {
productJson := `{
"opt1": 200,
"opt3": "1",
"opt4": "13",
"opt5": null,
"products": [
{ "product_id": 1, "price": 100, "variant_id": 100 },
{ "product_id": 1, "price": 100, "variant_id": null }
]
}`
productData := &ProductData{}
err := json.Unmarshal([]byte(productJson), &productData)
if err != nil {
panic(err)
}
b, err := json.Marshal(map[string]interface{}{"purchased_products": productData.Products})
if err != nil {
panic(err)
}
d := &Response{
Json: b,
CreatedAt: time.Now().Format("2006-01-02 15:04:05"),
UpdatedAt: time.Now().Format("2006-01-02 15:04:05"),
}
out, err := json.Marshal(d)
if err != nil {
panic(err)
}
log.Println(string(out))
}
输出:
2009/11/10 23:00:00 {"json":{"purchased_products":[{"product_id":1,"price":100,"variant_id":100},{"product_id":1,"price":100,"variant_id":0}]},"created_at":"2009-11-10 23:00:00","updated_at":"2009-11-10 23:00:00"}