Accessing sub keys/values in a map[string]interface{} variable

var x_inboundbody map[string]interface{}|
_ = json.Unmarshal(Inboundbody, &x_inboundbody)|

I have a 3…4 level deep structure, like a JSON structure (due to dynamic nature it’s not viable to pre create a struct), but it’s dynamic from record to record.

I do know that in my structure I have the following key’s from a root level entities.overalScore.overallScore that I want to access.

I want to extract the value 60 as per below.

Can anyone help.

G

The easiest way is to map your jsonto a go struct (use JSON-to-Go: Convert JSON to Go instantly) .
Otherwise you have to be aware, each element tahta you get from map is a struct{}, so it has to be convert to the appropiate data type. The code could be something like:

Inboundbody := []byte(json_string)
var x_inboundbody map[string]interface{}
_ = json.Unmarshal(Inboundbody, &x_inboundbody)
fmt.Println(x_inboundbody) // map[string]interface{}

responseBodyInterface := x_inboundbody["responseBody"]            // interface{}
responseBodyMap := responseBodyInterface.(map[string]interface{}) // map[string]interface{}
fmt.Printf("responseBodyMap :%T\n%v\n", responseBodyMap, responseBodyMap)

entitiesInterface := responseBodyMap["entities"]         // interface{}
entitiesSlice := entitiesInterface.([]interface{})       // []interface{}
entitiesMap := entitiesSlice[0].(map[string]interface{}) // map[string]interface{}
fmt.Printf("entitiesMap :%T\n%v\n", entitiesMap, entitiesMap)

overallScoreInterface := entitiesMap["overallScore"] // // interface{}
overallScoreMap := overallScoreInterface.(map[string]interface{})
fmt.Printf("overallScoreMap :%T\n%+v\n", overallScoreMap, overallScoreMap)
overallScore := overallScoreMap["overallScore"]
fmt.Printf("overallScore :%T\n%v\n", overallScore, overallScore)

HTH,
Yamil

See below error… I’m also adding showing where the inboundBody is coming from.

InboundRequest, _ := http.NewRequest("POST", vGeneral.Httpposturl, bytes.NewBuffer(InboundBytes))

InboundRequest.Header.Set("Content-Type", "application/json; charset=UTF-8")

InboundResponse, _ := client.Do(InboundRequest)
defer InboundResponse.Body.Close()

Inboundbody, _ = io.ReadAll(InboundResponse.Body)

//Inboundbody := []byte(json_string)
var x_inboundbody map[string]interface{}
_ = json.Unmarshal(Inboundbody, &x_inboundbody)
fmt.Println(x_inboundbody) // map[string]interface{}

responseBodyInterface := x_inboundbody["responseBody"]            // interface{}
responseBodyMap := responseBodyInterface.(map[string]interface{}) // map[string]interface{}
fmt.Printf("responseBodyMap :%T\n%v\n", responseBodyMap, responseBodyMap)
 Access-Control-Allow-Origin:[*] Cache-Control:[no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0] Connection:[keep-alive] Content-Length:[8044] Content-Type:[application/json] Date:[Thu, 05 Oct 2023 06:29:12 GMT] Server:[webserver] X-Content-Type-Options:[nosniff] X-Xss-Protection:[1; mode=block]]
2023/10/05 08:29:11 INFO: Inbound response Status       : 200 OK
2023/10/05 08:29:11 INFO: 
panic: interface conversion: interface {} is nil, not map[string]interface {}

goroutine 1 [running]:
main.runLoader({0x16d8bb33e?, 0x14000134a70?})
        /Users/george/Desktop/ProjectsCommon/fs/fs_scenario_tester2.2/cmd/producer.go:1166 +0x771c
main.main()
        /Users/george/Desktop/ProjectsCommon/fs/fs_scenario_tester2.2/cmd/producer.go:1688 +0x90
exit status 2
g-mbp.local:/Users/george/Desktop/ProjectsCommon/fs/fs_scenario_tester2.2 > ```

Maybe it’s easier to make a small runnable proof of concept of your problem on https://goplay.tools/? You could paste the problematic JSON there so we can collectively give parsing it a shot.

check if you are actually receiving data from your http call

I def am… as I’m saving it to a file.

G

full response body that I get as a byte from .

Inboundbody, err = io.ReadAll(InboundResponse.Body)

{
 "eventId": "651a10a9-71e0-4669-bc77-d1b79cb21a61",
 "eventType": "paymentRT",
 "processTime": "2023-10-05T16:25:21.861448Z",
 "responseBody": {
  "entities": [
   {
    "configGroups": [
     {
      "aggregators": [
       {
        "aggregateScore": 1,
        "aggregatorId": "Rule: BRPP08_Unusual_Behaviour_During_Probation_Period",
        "alert": true,
        "matchedBound": 1,
        "outputTags": [],
        "scores": {
         "rules": [
          {
           "ruleId": "BRPP08_Unusual_Behaviour_During_Probation_Period",
           "score": 1
          }
         ]
        },
        "suppressAlert": false,
        "suppressedTags": []
       },
       {
        "aggregateScore": 1,
        "aggregatorId": "Rule: PRPP01_Multiple_RPP_CRTRF",
        "alert": true,
        "matchedBound": 1,
        "outputTags": [],
        "scores": {
         "rules": [
          {
           "ruleId": "PRPP01_Multiple_RPP_CRTRF",
           "score": 1
          }
         ]
        },
        "suppressAlert": false,
        "suppressedTags": []
       }
      ],
      "rulesContributingEvents": {},
      "triggeredRules": [
       "BRPP08_Unusual_Behaviour_During_Probation_Period",
       "PRPP01_Multiple_RPP_CRTRF"
      ],
      "type": "global"
     }
    ],
    "entityId": "NEDSZAJ0-33345210002",
    "entityType": "ACCOUNT",
    "models": [
     {
      "confidence": null,
      "modelId": "businessrules",
      "score": 60,
      "tags": []
     }
    ],
    "outputTags": [],
    "overallScore": {
     "overallScore": 60
    },
    "riskStatus": "review",
    "tenantId": "NEDSZAJ0"
   },
   {
    "configGroups": [],
    "entityId": "CTT.creditor.identification.organisationIdentification or privateIdentification",
    "entityType": "ACCOUNTCUSTOMER",
    "models": [],
    "outputTags": [],
    "overallScore": {
     "overallScore": null
    },
    "riskStatus": "no-risk",
    "tenantId": "NEDSZAJ0"
   },
   {
    "configGroups": [],
    "entityId": "ABSAZAJ0-999777210016",
    "entityType": "COUNTERPARTY",
    "models": [],
    "outputTags": [],
    "overallScore": {
     "overallScore": null
    },
    "riskStatus": "no-risk",
    "tenantId": "NEDSZAJ0"
   },
   {
    "configGroups": [
     {
      "aggregators": [
       {
        "aggregateScore": 1,
        "aggregatorId": "Rule: PRPP03_Unusual_Activity_Spikes",
        "alert": true,
        "matchedBound": 1,
        "outputTags": [],
        "scores": {
         "rules": [
          {
           "ruleId": "PRPP03_Unusual_Activity_Spikes",
           "score": 1
          }
         ]
        },
        "suppressAlert": false,
        "suppressedTags": []
       }
      ],
      "rulesContributingEvents": {},
      "triggeredRules": [
       "PRPP03_Unusual_Activity_Spikes"
      ],
      "type": "global"
     }
    ],
    "entityId": "CTT.creditorAccount.proxy",
    "entityType": "ACCOUNTPROXY",
    "models": [
     {
      "confidence": null,
      "modelId": "businessrules",
      "score": 30,
      "tags": []
     }
    ],
    "outputTags": [],
    "overallScore": {
     "overallScore": 30
    },
    "riskStatus": "review",
    "tenantId": "NEDSZAJ0"
   },
   {
    "configGroups": [],
    "entityId": "CTT.debtorAccount.proxy",
    "entityType": "COUNTERPARTYPROXY",
    "models": [],
    "outputTags": [],
    "overallScore": {
     "overallScore": null
    },
    "riskStatus": "no-risk",
    "tenantId": "NEDSZAJ0"
   },
   {
    "configGroups": [],
    "entityId": "CTT.debtor.identification.organisationIdentification or privateIdentification",
    "entityType": "COUNTERPARTYCUSTOMER",
    "models": [],
    "outputTags": [],
    "overallScore": {
     "overallScore": null
    },
    "riskStatus": "no-risk",
    "tenantId": "NEDSZAJ0"
   }
  ],
  "jsonVersion": 4,
  "originatingEvent": {
   "_metadata": {
    "entities": {
     "ACCOUNT": [
      "NEDSZAJ0-33345210002"
     ],
     "ACCOUNTCUSTOMER": [
      "CTT.creditor.identification.organisationIdentification or privateIdentification"
     ],
     "ACCOUNTPROXY": [
      "CTT.creditorAccount.proxy"
     ],
     "COUNTERPARTY": [
      "ABSAZAJ0-999777210016"
     ],
     "COUNTERPARTYCUSTOMER": [
      "CTT.debtor.identification.organisationIdentification or privateIdentification"
     ],
     "COUNTERPARTYPROXY": [
      "CTT.debtorAccount.proxy"
     ]
    },
    "eventId": "651a10a9-71e0-4669-bc77-d1b79cb21a61",
    "eventTime": "2023-10-05T18:25:21Z",
    "eventType": "paymentRT",
    "execution": {
     "expectResponse": true
    },
    "financialValue": 1700,
    "receivedTime": "2023-10-05T16:25:21Z",
    "searchable": {
     "accountAddress": {
      "addressLine1": "CTT.creditor.streetName",
      "postalCode": "1234"
     },
     "accountAgentId": "NEDSZAJ0",
     "accountCustomerEntityId": "CTT.creditor.identification.organisationIdentification or privateIdentification",
     "accountCustomerId": "CTT.creditor.identification.organisationIdentification or privateIdentification",
     "accountEntityId": "NEDSZAJ0-33345210002",
     "accountId": "33345210002",
     "accountNumber": "33345210002",
     "accountProxyEntityId": "CTT.creditorAccount.proxy",
     "accountProxyId": "CTT.creditorAccount.proxy",
     "counterpartyAddress": {
      "addressLine1": "CTT.debtor.streetName",
      "postalCode": "5678"
     },
     "counterpartyAgentId": "ABSAZAJ0",
     "counterpartyCustomerEntityId": "CTT.debtor.identification.organisationIdentification or privateIdentification",
     "counterpartyCustomerId": "CTT.debtor.identification.organisationIdentification or privateIdentification",
     "counterpartyEntityId": "ABSAZAJ0-999777210016",
     "counterpartyId": "999777210016",
     "counterpartyName": {
      "fullName": "debtorAccount"
     },
     "counterpartyNumber": "999777210016",
     "counterpartyProxyEntityId": "CTT.debtorAccount.proxy",
     "counterpartyProxyId": "CTT.debtorAccount.proxy",
     "eventId": "651a10a9-71e0-4669-bc77-d1b79cb21a61",
     "eventTime": "2023-10-05T18:25:21",
     "eventType": "paymentRT",
     "paymentClearingSystemReference": "90dd9238-zzzz-5g5g-8356-0fcc8055k55k55",
     "requestExecutionDate": "2023-10-05",
     "settlementDate": "2023-10-05",
     "transactionId": "fe0fa93e-9272-4045-a73a-08d5a2101973"
    },
    "systemEventId": "20755-oq2nVdCv",
    "tenantId": [
     "NEDSZAJ0"
    ]
   },
   "accountAddress": {
    "addressLine1": "CTT.creditor.streetName",
    "addressLine2": "CTT.creditor.buildingNumber and buildingName",
    "country": "ZAF",
    "countrySubDivision": "CTT.creditor.countrySubDivision",
    "fullAddress": "CTT.creditor.addressLine",
    "postalCode": "1234",
    "townName": "CTT.creditor.townName"
   },
   "accountAgentId": "NEDSZAJ0",
   "accountBICFI": "NEDSZAJ0",
   "accountCustomerEntityId": "CTT.creditor.identification.organisationIdentification or privateIdentification",
   "accountCustomerId": "CTT.creditor.identification.organisationIdentification or privateIdentification",
   "accountDomain": "CTT.creditorAgent.domain",
   "accountEntityId": "NEDSZAJ0-33345210002",
   "accountId": "33345210002",
   "accountIdCode": "CTT.creditorAccount.type",
   "accountName": {
    "fullName": "creditorAccount",
    "namePrefix": "CTT",
    "surname": "Name"
   },
   "accountNumber": "33345210002",
   "accountProxyEntityId": "CTT.creditorAccount.proxy",
   "accountProxyId": "CTT.creditorAccount.proxy",
   "accountProxyType": "CTT.creditorAccount.proxyType",
   "amount": {
    "baseCurrency": "zar",
    "baseValue": 1700,
    "currency": "zar",
    "value": 1700
   },
   "chargeBearer": "SLEV",
   "counterpartyAddress": {
    "addressLine1": "CTT.debtor.streetName",
    "addressLine2": "CTT.debtor.buildingNumber and buildingName",
    "country": "ZAF",
    "countrySubDivision": "CTT.debtor.countrySubDivision",
    "fullAddress": "CTT.debtor.addressLine",
    "postalCode": "5678",
    "townName": "CTT.debtor.townName"
   },
   "counterpartyAgentId": "ABSAZAJ0",
   "counterpartyBICFI": "ABSAZAJ0",
   "counterpartyCustomerEntityId": "CTT.debtor.identification.organisationIdentification or privateIdentification",
   "counterpartyCustomerId": "CTT.debtor.identification.organisationIdentification or privateIdentification",
   "counterpartyDomain": "CTT.debtorAgent.domain",
   "counterpartyEntityId": "ABSAZAJ0-999777210016",
   "counterpartyId": "999777210016",
   "counterpartyIdCode": "CTT.debtorAccount.type",
   "counterpartyName": {
    "fullName": "debtorAccount",
    "namePrefix": "CTT",
    "surname": "Name"
   },
   "counterpartyNumber": "999777210016",
   "counterpartyProxyEntityId": "CTT.debtorAccount.proxy",
   "counterpartyProxyId": "CTT.debtorAccount.proxy",
   "counterpartyProxyType": "CTT.debtorAccount.proxyType",
   "creationDate": "2023-10-05T18:25:21",
   "direction": "inbound",
   "eventId": "651a10a9-71e0-4669-bc77-d1b79cb21a61",
   "eventTime": "2023-10-05T18:25:21",
   "eventType": "paymentRT",
   "fromId": "ABSAZAJ0",
   "instructedAgentId": "CTT.instructedAgent.BICFI",
   "instructingAgentId": "CTT.instructingAgent.BICFI",
   "intermediaryAgent1Id": "CTT.intermediaryAgent1.BICFI",
   "intermediaryAgent2Id": "CTT.intermediaryAgent2.BICFI",
   "localInstrument": "PBAC",
   "msgStatus": "New",
   "msgType": "CRTRF",
   "numberOfTransactions": 1,
   "paymentClearingSystemReference": "90dd9238-zzzz-5g5g-8356-0fcc8055k55k55",
   "paymentMethod": "TRF",
   "paymentReference": "CTT.remittanceinformation.structured.creditorReference",
   "remittanceId": "CTT.paymentidentification.endToEndIdentification",
   "requestExecutionDate": "2023-10-05",
   "schemaVersion": 1,
   "settlementClearingSystemCode": "RPP",
   "settlementDate": "2023-10-05",
   "settlementMethod": "CLRG",
   "tenantId": "NEDSZAJ0",
   "toId": "NEDSZAJ0",
   "transactionId": "fe0fa93e-9272-4045-a73a-08d5a2101973",
   "transactionType": "CTT.purposeCode",
   "ultimateAccountName": {
    "fullName": "ultimateCreditor",
    "namePrefix": "CTT",
    "surname": "Name"
   },
   "ultimateCounterpartyName": {
    "fullName": "ultimateDebtor",
    "namePrefix": "CTT",
    "surname": "Name"
   },
   "unstructuredRemittanceInformation": "CTT.remittanceinformation.unstructured",
   "verificationResult": "SUCC"
  },
  "outputTime": "2023-10-05T16:25:21.830Z",
  "processorId": "proc",
  "statusCode": "success",
  "versions": {
   "configGroups": [
    {
     "id": "210002",
     "type": "analytical",
     "version": "0"
    },
    {
     "type": "global",
     "version": "1"
    }
   ],
   "modelGraph": 1
  }
 },
 "responseHeaders": {
  "Access-Control-Allow-Headers": [
   "Origin, X-Requested-With, Content-Type, Content-Length, Accept"
  ],
  "Access-Control-Allow-Origin": [
   "*"
  ],
  "Cache-Control": [
   "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"
  ],
  "Connection": [
   "keep-alive"
  ],
  "Content-Length": [
   "8155"
  ],
  "Content-Type": [
   "application/json"
  ],
  "Date": [
   "Thu, 05 Oct 2023 16:25:21 GMT"
  ],
  "Server": [
   "webserver"
  ],
  "X-Content-Type-Options": [
   "nosniff"
  ],
  "X-Xss-Protection": [
   "1; mode=block"
  ]
 },
 "responseStatus": "200 OK",
 "transactionId": "fe0fa93e-9272-4045-a73a-08d5a2101973"
}

I stripped down the JSON to make it easier to do the bare minimum you ask for.
Running example:
https://goplay.tools/snippet/RIjLk-G-2u8

The website @Yamil_Bracho mentioned, is indeed very helpful in generating the struct but in this case I could also clean up the struct-tags (json: ...) because the variables have the right name already.

func main() {

	type Rsp struct {
		ResponseBody struct {
			Entities []struct {
				OverallScore struct {
					OverallScore int
				}
			}
		}
	}

	var rsp Rsp

	json.Unmarshal([]byte(rawJsonString), &rsp)

	for _, v := range rsp.ResponseBody.Entities {
		fmt.Println(v.OverallScore.OverallScore)
	}

}

As said in OP,

I cannot define a struct for this as it’s to dynamic the response.
I’ve only shown one response, I have 15. all coming back from the same call, only once I’ve gotten it and got into a reference able object then only can I figure out which payload it is.

G

Check for emptyness/existence in the parsed response?
Or just parse the response partially in a first pass, to discriminate between the different responses?

json.RawMessage is probably your friend here. Check out this example where they don’t know what the child type will be initially:

can sort of imagine how this could work, if I think my structures was simpler.
would really have been great if there was a simple function that took a byte and returned an addressable json object that could have been referenced a := jsonObjName[“attribute”][“subAttribute”]

thinking especially since this language was created around API’s and at times the inbound structure might not be 100% known, but some attributes is known to always be present.
G

solution is crude, but works…



InboundRequest, _ := http.NewRequest("POST", vGeneral.Httpposturl, bytes.NewBuffer(InboundBytes))

InboundRequest.Header.Set("Content-Type", "application/json; charset=UTF-8")

InboundResponse, _ := client.Do(InboundRequest)
defer InboundResponse.Body.Close()

jsonDataOutboundResponsebody, _ = io.ReadAll(InboundResponse.Body)

var outboundbodyMap map[string]interface{}

_ = json.Unmarshal(jsonDataOutboundResponsebody, &outboundbodyMap)

// Access the nested array
entities, ok := inboundbodyMap["entities"].([]interface{})
if !ok {
	fmt.Println("Error accessing entities")
	return
}

var vScore float64
vScore = 0.0
for _, entity := range entities {
	overallScoreMap, ok := entity.(map[string]interface{})
	if !ok {
		fmt.Println("Error accessing entity details")
		return
	}

	// Access the details map for each language
	overallScores, ok := overallScoreMap["overallScore"].(map[string]interface{})
	if !ok {
		fmt.Println("Error accessing language details")
		return
	}
	for _, value := range overallScores {
		if value != nil {
			if value.(float64) > float64(vScore) {
				vScore = value.(float64)
			}
		}
	}
}
fmt.Println(vScore)

It’s a nice exercise comparing the map[string]interface{}- vs. the struct-json-API.
But I guess in the end it all depends on what exactly is known about the variance in your responses so you can find the optimal position to error out or decide on the contents of the rest of the message.

I understand the frustration but I’m not too sure if in the end this would be easier in Python or something? The hard part is always the error handling.

1 Like

I play in Python also, this is allot easier that side :wink:

This piece of work is at the moment just to far to pivot over to Python.

But might do it at some point.

G

I wouldn’t say you should switch to Python. I can’t stand it that there is no compiler to catch errors. Compilers IMO are the most important refactoring tool.

But I’m pretty sure you’re not yet quite to the most optimal form in Go.
For one there’s a risk of running in a panic when casting interface{} to float without checking for ok. (You’re not doing that with the vScore.)

This code demonstrates that you can cast without ok but it generates a panic if the cast fails:

var i1 interface{} = 3.14

	fmt.Println(i1)

	f1, ok := i1.(float64)

	fmt.Println(ok)
	fmt.Println(f1)

	var i2 interface{} = "not a float"

	fmt.Println(i2)

	//var f2 float64

	f2, ok := i2.(float64) // this won't panic because there's an ok

	fmt.Println(ok)
	fmt.Println(f2)

	f3 := i2.(float64) // this can panic

	fmt.Println(f3)

I also just learned that when ok is there, it won’t panic. Interesting.

1 Like

modified my for loop a bit, incorporating the cast as float suggest.


for _, value := range overallScores {
	if value != nil {
		f, ok := value.(float64) // this won't panic because there's an ok
		if ok {
			if f > float64(vScore) {
				vScore = f
			}
		}
	}
}

or

for _, value := range overallScores {
	if value != nil {
		f, ok := value.(float64) // this won't panic because there's an ok
		if ok && f > float64(vScore){
			vScore = f
		}
	}
}

… solution compiled with suggestion from here… and prompting ChatGPT with ideas, and guiding those questions more…

funky :wink:

G

Here’s a more correct (in my opinion) way of handling this. I’m assuming the event type is the thing that tells you what the shape of the data will be. Let’s use json.RawMessage in a struct:

type SomeEvent struct {
	EventType    string
	ResponseBody json.RawMessage
}

Next, using json-to-go, I auto-generated a struct with the data for the paymentRT event type:

type RaymentRTResponseBody struct {
	Entities []struct {
		ConfigGroups []struct {
			Aggregators []struct {
				AggregateScore int    `json:"aggregateScore"`
				AggregatorID   string `json:"aggregatorId"`
				Alert          bool   `json:"alert"`
				MatchedBound   int    `json:"matchedBound"`
				OutputTags     []any  `json:"outputTags"`
				Scores         struct {
					Rules []struct {
						RuleID string `json:"ruleId"`
						Score  int    `json:"score"`
					} `json:"rules"`
				} `json:"scores"`
				SuppressAlert  bool  `json:"suppressAlert"`
				SuppressedTags []any `json:"suppressedTags"`
			} `json:"aggregators"`
			RulesContributingEvents struct {
			} `json:"rulesContributingEvents"`
			TriggeredRules []string `json:"triggeredRules"`
			Type           string   `json:"type"`
		} `json:"configGroups"`
		EntityID   string `json:"entityId"`
		EntityType string `json:"entityType"`
		Models     []struct {
			Confidence any    `json:"confidence"`
			ModelID    string `json:"modelId"`
			Score      int    `json:"score"`
			Tags       []any  `json:"tags"`
		} `json:"models"`
		OutputTags   []any `json:"outputTags"`
		OverallScore struct {
			OverallScore int `json:"overallScore"`
		} `json:"overallScore"`
		RiskStatus string `json:"riskStatus"`
		TenantID   string `json:"tenantId"`
	} `json:"entities"`
}

You can omit the fields you don’t care about. Next, let’s use it:

func main() {
	var resp SomeEvent
	// Excluded for the sake of brevity but:
	// const input = `that long json string you posted earlier`
	json.Unmarshal([]byte(input), &resp)
	// Event Type determines what type of data is returned.
	switch resp.EventType {
	case "paymentRT":
		var dst RaymentRTResponseBody
		err := json.Unmarshal(resp.ResponseBody, &dst)
		if err != nil {
			log.Fatal("error:", err)
		}
		for _, v := range dst.Entities {
			fmt.Println("Entity ID:", v.EntityID)
			fmt.Println("Overall score:", v.OverallScore.OverallScore)
			fmt.Println("----")
		}
	case "otherEventType":
		// Handle your other stuff similarly
	default:
		log.Fatal("Unsupported event type:", resp.EventType)
	}
}

This prints:

Entity ID: NEDSZAJ0-33345210002
Overall score: 60
----
Entity ID: CTT.creditor.identification.organisationIdentification or privateIdentification
Overall score: 0
----
Entity ID: ABSAZAJ0-999777210016
Overall score: 0
----
Entity ID: CTT.creditorAccount.proxy
Overall score: 30
----
Entity ID: CTT.debtorAccount.proxy
Overall score: 0
----
Entity ID: CTT.debtor.identification.organisationIdentification or privateIdentification
Overall score: 0
----

As noted, you can add support for other event types as easily as copying and pasting your json into json-to-go. You can run this yourself here on the playground:

1 Like

so i was able to compile a super set struct that should/would cover the various messages/responses.

Now that I got the one (above) method working,

going to create a second as per above (and @Dean_Davidson below example), by casting to struct.

:slight_smile:

G