How to access struct inside a struct using go lang


(Subha Sahu) #1

I have written a go language to read value from a struct and display the value of required fields.

My go code is as below

//==================================================================================================
//================================== 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"
}

I have written function to do some validation,function code is as below
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())
}

}

I am getting the below error:
json: cannot unmarshal array into Go value of type main.salesorder

Can some body suggest how can i get the fields from inner struct.


(Johan Dahl) #2

Hi

You must make all fields which should be filled from json exported. That is name them with a capital in the beginning. So

should be

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

And also to make it easier for others to read your code put it between two lines ```go before the code and ``` after the code (three backticks)


(Subha Sahu) #3

Dear All,

I have written the code to fetch the record from a ledger in blockchain and assign the value to a struct. But while assign the values to struct I am getting error

Posting the sample code

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 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:"InvoiceNo"
Invoicedate string json:"Invoicedate"
BillTo string json:"BillTo"
Item string json:"Item"
Amount float64 json:"Amount"
}
//=================================================================================================
//============================================= VALIDATE ==========================================

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 Sales salesorder
var Receipt receiptdetails
var Invoice invoicedetails

//var Purchase []purchaseOrder
//var Sales []salesorder
//var Receipt []receiptdetails
//var Invoice []invoicedetails

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


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

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


//if (Receipt[0].Status == "Delivered" && Invoice[0].Amount == Sales[0].Value && Sales[0].Value == Purchase[0].Amount){

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())  
}

}

I am checking through swagger UI
GET [/Validate/{id}/{SOId}/{RCId}/{INId}

Error message:

{
“error”: {
“message”: “json: cannot unmarshal array into Go value of type main.invoicedetails”,
“code”: “CustomError”,
“status”: 500
}
}


(Manxiaqu) #4

Based on information you supply, it seems that there are some error in err = json.Unmarshal(bytes3, &Invoice). According to error message, bytes3 may be a array.
you can try

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

and, check value of data, then define a struct can unmarshal by json.


(Subha Sahu) #5

Hi,

I have check the below code , Its working fine but in code its throwing error

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())  
}

}

Please suggest how can i debug my code or write error message as I am unable to debug my code in swagger UI.


(Subha Sahu) #6

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)

}

This code is working fine in https://play.golang.org/ but if i implement the same code in above post it is throwing error cannot unmarshal array into Go value of type main.invoicedetails


(Subha Sahu) #7

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

It gives me error like
no new variables on left side of :=
cannot use data (type interface {}) as type string in argume
nt to fmt.Printf: need type assertion


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

err may have been declared before is the reason that throws error “no new variables on left side of :=”; In order to deep into what’s your problem is, can you post a link to your full code if you feel ok?


(Subha Sahu) #9

Hi,

Can you tell me how to unmarshal a nested json

My code is :

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)

}