1

我有这样的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"`
}

然后我使用解组

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"),
}

我该怎么做?

4

5 回答 5

2

如下创建一个类型(例如:PurchableProducts)。

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"),
    }

您可以在此处运行并查看完整代码。

于 2021-07-02T06:28:45.747 回答
1

对于可为空的字段,您可以使用指针,例如,如果variant_idjson 字段可以是整数或 json null,并且您希望保留该信息,则可以更改Variant_id intVariant_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是 type 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))
}

https://play.golang.org/p/0gnrjgUslza

于 2021-07-02T06:36:57.987 回答
1

只需定义另外两个对第二个 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. 如果您将该字段声明为 simple 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
}

游乐场: https: //play.golang.org/p/xhsmHNBjRKN

于 2021-07-02T06:38:23.547 回答
0

给你。假设是:

  • 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)
    }
}
于 2021-07-02T06:30:18.263 回答
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"}
于 2021-07-02T13:27:06.493 回答