Golang中如何访问嵌套结构体

Golang中如何访问嵌套结构体 我编写了一个Go语言程序来从结构体中读取值并显示所需字段的值。

我的Go代码如下

//==================================================================================================
//================================== STRUCT FOR ALL ================================================
type purchaseOrder struct {
PONo           string         `json:"PONo"`
OrderDate      string         `json:"OrderDate"`
//  ItemQty        int            `json:"ItemQty"`
ExpDelDate     string         `json:"ExpDelDate"`
ActualDelDate  string         `json:"ActualDelDate"`
DeliveryAdd    string         `json:"DeliveryAdd"`
Status         string         `json:"Status"`
Amount         float64        `json:"Amount"`
Product_lists []Product_Details `json:"Product_lists"`
salesorder     salesorder     `json:"Salesorder"`
receiptdetails receiptdetails `json:"Receiptdetails"`
invoicedetails invoicedetails `json:"Invoicedetails"`
APAR_Details   APAR_Details   `json:"apar_details"`
}
type salesorder struct {
SOnum        string `json:"SOnum"`
ShipTo       string `json:"ShipTo"`
Companyname  string `json:"Companyname"`
Address      string `json:"Address"`
Quantity     int    `json:"Quantity"`
Deliverydate string `json:"Deliverydate"`
Unitprice    string `json:"Unitprice"`
Value        float64 `json:"Value"`
Purchasedate string `json:"Purchasedate"`
}
type receiptdetails struct {
ReceiptNo      string      `json:"receiptNo"`
Creationdate   string      `json:"creationdate"`
Status         string      `json:"status"`
Description    string      `json:"description"`
}

type invoicedetails struct {
InvoiceNo      string `json:"ReceiptNo"`
Invoicedate    string `json:"Invoicedate"`
BillTo         string `json:"BillTo"`
Item           string `json:"Item"`
Amount         float64 `json:"Amount"`
}
type Product_Details struct {
ItemNo   string `json:"itemNo"`
ItemName string `json:"itemName"`
Quantity int `json:"quantity"`
itemPrice float64 `json:"itemPrice"`
Value float64 `json:"Value"`
}

我编写了一个函数来进行一些验证,函数代码如下:

func (t *Actpay) Validate(stub shim.ChaincodeStubInterface, args []string) peer.Response {

fmt.Println("Validate using 3 way matching")
if len(args) != 4 {
   return shim.Error("Incorrect Number of arguments.Expecting 4 for validation")
}
// Fetching PO details from ledger
var PoId = strings.ToLower(args[0])
bytes, err := stub.GetState(PoId)
    var SoId = strings.ToLower(args[1])
bytes1, err := stub.GetState(SoId)
var RCId = strings.ToLower(args[2])
bytes2, err := stub.GetState(RCId)
   var INId = strings.ToLower(args[3])
   bytes3, err := stub.GetState(INId)
if err != nil {
   return Error(http.StatusInternalServerError, err.Error())
}

var Purchase purchaseOrder
var Receipt receiptdetails
var Invoice invoicedetails
var Sales salesorder

err = json.Unmarshal(bytes, &Purchase)
err = json.Unmarshal(bytes1, &Sales)
err = json.Unmarshal(bytes2,&Receipt)
err = json.Unmarshal(bytes3, &Invoice)

if (Receipt.Status == "Delivered" && Invoice.Amount == Sales.Value && Sales.Value == Purchase.Amount){
   return Success(http.StatusCreated, "validated", nil)	   
} else {
  return Error(http.StatusInternalServerError, err.Error())
}

我遇到了以下错误: json: cannot unmarshal array into Go value of type main.salesorder

有人可以建议如何从内部结构体中获取字段吗?


更多关于Golang中如何访问嵌套结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

如果我使用

var data interface{}
err := json.Unmarshal(bytes3, &data)

会出现如下错误: 左侧没有新变量可用于 := 不能在 fmt.Printf 参数中使用 data(类型为 interface{})作为字符串类型:需要进行类型断言

更多关于Golang中如何访问嵌套结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


err := json.Unmarshal(bytes3, &data)

错误可能是在之前已经声明过,这是导致"左侧:=没有新变量"错误的原因;为了深入了解您的问题所在,如果您方便的话,能否提供完整代码的链接?

根据您提供的信息,似乎 err = json.Unmarshal(bytes3, &Invoice) 这行代码存在一些错误。根据错误信息,bytes3 可能是一个数组。

您可以尝试:

var data interface{}
err := json.Unmarshal(bytes3, &data)

然后检查 data 的值,再定义一个可以通过 json 进行反序列化的结构体。

你好

必须将所有需要从 JSON 填充的字段设置为可导出。也就是说,字段名要以大写字母开头。所以

Product_lists []Product_Details `json:"Product_lists"`
salesorder salesorder `json:"Salesorder"`
receiptdetails receiptdetails `json:"Receiptdetails"`
invoicedetails invoicedetails `json:"Invoicedetails"`
APAR_Details APAR_Details `json:"apar_details"`

}

应该改为

Salesorder salesorder `json:"Salesorder"`
Receiptdetails receiptdetails `json:"Receiptdetails"`
Invoicedetails invoicedetails `json:"Invoicedetails"`

另外为了让其他人更容易阅读你的代码,请在代码前后使用 go 和 将其包裹起来(三个反引号)

package main

import (
"encoding/json"
"log"

)
type invoicedetails struct {
InvoiceNo      string `json:"InvoiceNo"`
Invoicedate    string `json:"Invoicedate"`
BillTo         string `json:"BillTo"`
Item           string `json:"Item"`
Amount         float64 `json:"Amount"`
}
var body_byte = []byte(`{ "invoiceNo": "IN130", "invoicedate": "2018-11-22T12:16:42.444Z", "billto": "TCS", "item": "Office", "amount": 100 }`)

func main() {
data := &invoicedetails{}
json.Unmarshal(body_byte, &data)
log.Println(data.Item)

}

这段代码在 https://play.golang.org/ 中可以正常运行,但如果在上述帖子中实现相同的代码,会抛出错误:无法将数组解组为 Go 类型 main.invoicedetails

你好,

能否告诉我如何解析嵌套的 JSON?

我的代码是:

package main

import (
"encoding/json"
"log"

)
type purchaseOrder struct {
PONo           string         `json:"PONo"`
OrderDate      string         `json:"OrderDate"`
ExpDelDate     string         `json:"ExpDelDate"`
ActualDelDate  string         `json:"ActualDelDate"`
DeliveryAdd    string         `json:"DeliveryAdd"`
Status         string         `json:"Status"`
Amount         float64        `json:"Amount"`
Product_lists []Product_Details `json:"Product_lists"`
}

type Product_Details struct {
ItemNo   string `json:"ItemNo"`
ItemName string `json:"ItemName"`
Quantity int `json:"Quantity"`
ItemPrice float64 `json:"ItemPrice"`
Value float64 `json:"Value"`
}

var body_byte = []byte(`[ { "Orderid": "PO160", "Orderdate:": "2018-11-22T10:30:44.790Z", "Expdeldate": "2018-11-22T10:30:44.790Z", "ActualdelDate": "2018-11-22T10:30:44.790Z", "Deliveryadd": "2018-11-22T10:30:44.790Z", "Status": "SO_GENERATED", "Amount": 100, "Product_Details": [ { "ItemNo": "1", "ItemName": "Office", "Quantity": 2, "ItemPrice": 25, "Value": 50 } ] }]`)

func main() {
var data []purchaseOrder
json.Unmarshal(body_byte, &data)
log.Println(data)

}

我已经检查了下面的代码,它运行正常,但在代码中会抛出错误

func (t *Actpay) Validate(stub shim.ChaincodeStubInterface, args []string) peer.Response {
fmt.Println("Validate using 3 way matching")
if len(args) != 4 {
   return shim.Error("Incorrect Number of arguments.Expecting 4 for validation")
}
// Fetching PO details from ledger
var PoId = strings.ToLower(args[0])
bytes, err := stub.GetState(PoId)
var SoId = strings.ToLower(args[1])
bytes1, err := stub.GetState(SoId)
var RCId = strings.ToLower(args[2])
bytes2, err := stub.GetState(RCId)
var INId = strings.ToLower(args[3])
bytes3, err := stub.GetState(INId)
if err != nil {
   return Error(http.StatusInternalServerError, err.Error())
}

Purchase := &purchaseOrder{}
Sales := &salesorder{}
Receipt := &receiptdetails{}
Invoice := &invoicedetails{}

err = json.Unmarshal(bytes, &Purchase)
err = json.Unmarshal(bytes1, &Sales)
err = json.Unmarshal(bytes2, &Receipt)
err = json.Unmarshal(bytes3, &Invoice)



logger.Debug("Going for validation")

if (Receipt.Status == "Delivered"){
    if (Invoice.Amount == Sales.Value){
       if (Sales.Value == Purchase.Amount){
	       return Success(http.StatusOK, "validated", nil)
	   }else {
           return Error(http.StatusInternalServerError, err.Error())
	   }
    }else {
       return Error(http.StatusInternalServerError, err.Error())
	}
}else {
    return Error(http.StatusInternalServerError, err.Error())  
}

请建议我如何调试代码或编写错误信息,因为我无法在Swagger UI中调试我的代码。

在Go语言中访问嵌套结构体时,需要使用点操作符来逐级访问内部字段。根据您的代码和错误信息,问题可能出现在JSON数据与结构体类型的匹配上。

以下是访问嵌套结构体字段的正确方式:

// 访问purchaseOrder中的嵌套结构体字段示例
fmt.Printf("Sales Order Number: %s\n", Purchase.salesorder.SOnum)
fmt.Printf("Receipt Status: %s\n", Purchase.receiptdetails.Status)
fmt.Printf("Invoice Amount: %.2f\n", Purchase.invoicedetails.Amount)

// 在您的验证逻辑中,应该这样访问
if (Purchase.receiptdetails.Status == "Delivered" && 
    Purchase.invoicedetails.Amount == Purchase.salesorder.Value && 
    Purchase.salesorder.Value == Purchase.Amount) {
    return Success(http.StatusCreated, "validated", nil)
}

关于您遇到的JSON反序列化错误,问题在于您尝试将数组数据反序列化为单个结构体对象。根据您的purchaseOrder结构体定义,salesorder、receiptdetails和invoicedetails都是单个对象,而不是数组。

检查您的JSON数据格式是否正确:

  • 如果JSON中的对应字段是数组,应该使用切片类型
  • 如果JSON中的对应字段是对象,使用结构体类型是正确的

例如,如果JSON数据中"Salesorder"是数组,应该修改结构体为:

type purchaseOrder struct {
    // ... 其他字段
    Salesorder     []salesorder     `json:"Salesorder"`
    // ... 其他字段
}

如果JSON数据中"Salesorder"是单个对象,那么您的结构体定义是正确的,需要确保传入的JSON数据格式匹配。

在验证函数中直接访问嵌套字段:

// 验证嵌套结构体字段
if Purchase.receiptdetails.Status == "Delivered" {
    fmt.Println("Receipt status is delivered")
}

if Purchase.invoicedetails.Amount == Purchase.salesorder.Value {
    fmt.Printf("Invoice amount %.2f matches sales value %.2f\n", 
        Purchase.invoicedetails.Amount, Purchase.salesorder.Value)
}

确保JSON数据的结构与您的Go结构体定义完全匹配,这是解决反序列化错误的关键。

回到顶部