英文:
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"),
}
我该如何做到这一点?
英文:
I have json data like this:
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}]}
I have structured it using
type Products struct {
Product_id int
Price json.Number
Variant_id int
}
type Pdata struct {
Products []Products `json:"products"`
}
Then I use unmarshal
jsonb := []byte(jsonVal)
var data Pdata
err := json.Unmarshal(jsonb, &data)
if err != nil {
fmt.Println(err)
return
}
And get output like
{[{1 100 100} {2 100 0}]}
Now I need to convert that data into a json object like this
{"purchased_products": [{"product_id": 1,"price": 1200,"variation_id": 100},{"product_id": 2,"price": 100,"variation_id": null}]}
After that, I need to assign it to "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"),
}
How can I do it?
答案1
得分: 2
创建一个名为PurchasedProducts的类型,如下所示。
type PurchasedProducts struct {
Products []Products `json:"purchased_products"`
}
然后,初始化一个PurchasedProducts类型的变量,并将解码后的产品赋值给PurchasedProducts,如下所示。
pProducts := PurchasedProducts{Products: data.Products}
jsonByte, err := json.Marshal(pProducts)
if err != nil {
fmt.Println(err)
return
}
将该[]byte
数组转换为字符串,并将其赋值给map,如下所示。
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"),
}
你可以在这里运行并查看完整的代码。
英文:
Create a type (eg : PurchasedProducts) as below.
type PurchasedProducts struct {
Products []Products `json:"purchased_products"`
}
And init a PurchasedProducts type variable and assign your unmarshaled products to Purchased products as below.
pProducts := PurchasedProducts{Products: data.Products}
jsonByte, err := json.Marshal(pProducts)
if err != nil {
fmt.Println(err)
return
}
And convert that []byte
array to a string and assign it to the map like below.
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"),
}
You can run and see full code here.
答案2
得分: 1
对于可为空的字段,您可以使用指针。例如,如果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"`
}
要在解组和编组之间更改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"` // 这里的 variant_id 变成了 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() {
// 解组
var pd Pdata
err := json.Unmarshal(data, &pd)
if err != nil {
panic(err)
}
// 编组
out, err := json.MarshalIndent(pd, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
链接:https://play.golang.org/p/0gnrjgUslza
英文:
For nullable fields you can use pointers, so for example if the variant_id
json field can be an integer or a json null
, and you want to retain that information, then you can change Variant_id int
to Variant_id *int
.
type Product struct {
Product_id int `json:"product_id"`
Price json.Number `json:"price"`
Variant_id *int `json:"variant_id"`
}
To change json field names between unmarshal and marshal you can declare a second Products
struct with the same fields as the original but with struct tags defining the desired field names, then, if the structs are, in all other respects, equivalent you can convert between them.
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
}
Then, if p
is of type Product
, you can simply convert it to PurchasedProduct
like so:
pp := PurchasedProduct(p)
To offload the conversion to the marshaling process you can have the original types implement the json.Marshaler
interface and do the conversion there.
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))
}
With the above you can do the following:
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))
}
答案3
得分: 1
只需定义另外两个结构体来模拟第二个JSON对象:
type Pdata2 struct {
PurchasedProducts []Product2
}
type Product2 struct {
Product_id int
Price json.Number
Variation_id *int // 指向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 {
// ... 处理错误
}
var d = map[string]string{
"json": string(b),
// ...
}
fmt.Println(d)
}
func nullableInt(n int) *int {
if n == 0 {
return nil
}
return &n
}
Playground: https://play.golang.org/p/xhsmHNBjRKN
英文:
Simply define two more structs that model the second JSON object:
type Pdata2 struct {
PurchasedProducts []Product2
}
type Product2 struct {
Product_id int
Price json.Number
Variation_id *int // pointer to int
}
The Variation_id
field is an *int
type because your required output JSON shows "variation_id": null
. If you declare the field as simple int
, its zero value will be marshaled to 0
.
Then initialize those structs using values from the previous ones:
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
}
Playground: https://play.golang.org/p/xhsmHNBjRKN
答案4
得分: 0
给你翻译好的代码如下:
package main
import (
"encoding/json"
"log"
"os"
"time"
)
type (
Product struct {
ProductID int `json:"product_id"`
VariantID int `json:"variant_id"`
Price json.Number `json:"price"`
}
Products []Product
OutputProduct struct {
ProductID int `json:"product_id"`
VariantID int `json:"variation_id"`
Price json.Number `json:"price"`
}
)
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)
}
}
希望对你有帮助!
英文:
Here you are.
Assumptions are that:
- Product is a model which could be much more complicated, thus it has dedicated structs. Thus transformation from Product to OutputProduct can be unit tested separately.
- It is one time use application, not a part of the application which exposes an API. Otherwise it should be properly separated into layers and the output should be written as a structure.
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)
}
}
答案5
得分: 0
根据评论中的建议:
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"}
英文:
Based on the suggestions from comments:
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))
}
Output:
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"}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论