I am using an API, which returns a field that is sometimes a boolean, sometimes a string.
like this:
{
"unstable":true,
"unstable_reason":"ANY_REASON"
}
and
{
"unstable":false
"unstable_reason":false
}
the struct looks like this:
...
Unstable bool `json:"unstable"`
UnstableReason string `json:"unstable_reason,string"`
...
When trying to use this, I get the following error:
panic: json: invalid use of ,string struct tag, trying to unmarshal unquoted value into string
On the other hand, when using bool for UnstableReason, an error occurs aswell.
When removing ,string, I get this error:
panic: json: cannot unmarshal bool into Go struct field .data.prices.unstable_reason of type string
The field is not relevant for my purposes, so if there is a way to just let it be nil, this would also be fine.
I have no impact on the API.
Any Ideas? I am relatively new to go.
You can use interface{} type like as:
type YourMessage struct {
Unstable bool `json:"unstable"`
UnstableReason interface{} `json:"unstable_reason"`
}
func (m YourMessage) UnstableReasonAsString() string {
return fmt.Sprint(m.UnstableReason)
}
...
m1 := &YourMessage{}
if err := json.Unmarshal([]byte(messageJson), m1); err != nil {
fmt.Println("Error", err)
} else {
fmt.Println("Unstable Reason=", m1.UnstableReasonAsString())
}
Related
I'm having a hard time unmarshalling a struct that is sent to me from an AWS lambda function.
All of the pkidata fields are empty no matter what I do. I created this code sample to isolate the process :
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
)
func main() {
mystring := `{"error":{"errormessage": "errormessagetest", "errortype": "errortypetest"}, "pkidata":{"certificate":"Q2VydGlmaWNhdGU6CiAgICBEYXRhOgogICAgICAgIFZlcnNpb246IDMgKDB4MikKICAgICAgICBTZXJpYWwgTnVtYmVyOgogICAgICAgICAgICBhYTo5MzpiMTo4MDphYjpiYTplYzo5ZTo4MzpmOTo2OTo5NToyNDpkZjo5Njo2OQogICAgU2lnbmF0dXJlIEFsZ29yaXRobTogc2hhMjU2V2l0aFJTQUVuY3J5cHRpb24KICAgICAgICBJc3N1ZXI6IENOPXJhcGhvZXN0ZXIKICAgICAgICBWYWxpZGl0eQogICAgICAgICAgICBOb3QgQmVmb3JlOiBNYXIgMjcgMTk6NDM6MTQgMjAyMiBHTVQKICAgICAgICAgICAgTm90IEFmdGVyIDogSnVuIDI5IDE5OjQzOjE0IDIwMjQgR01UCiAgICAgICAgU3ViamVjdDogQ049cmFwaG9lc3RlcgogICAgICAgIFN1YmplY3QgUHVibGljIEtleSBJbmZvOgogICAgICAgICAgICBQdWJsaWMgS2V5IEFsZ29yaXRobTogcnNhRW5jcnlwdGlvbgogICAgICAgICAgICAgICAgUHVibGljLUtleTogKDIwNDggYml0KQogICAgICAgICAgICAgICAgTW9kdWx1czoKICAgICAgICAgICAgICAgICAgICAwMDpjNjplZjpkNjoxYTo0Mjo0Mjo2ZTo5MTpiODpmNTpiZjoyNToyNTpkODoKICAgICAgICAgICAgICAgICAgICBhNjo4Yjo4MzpmYjo2ZDo4MzpiNjowZTo3Mzo4ZjowYTozMjo5ZjpjNjplMjoKICAgICAgICAgICAgICAgICAgICBmMTo4Njo5NDoxMzo5MjplYjo0MTozNTo4NTpiZDo0ZDpkNzowNzo4ZTo5YjoKICAgICAgICAgICAgICAgICAgICBjYzoyYzpkMjo2Nzo5ZDpjOTo1Mzo4Yjo4ODpjZToxMTozOTpkODpkZTo3MjoKICAgICAgICAgICAgICAgICAgICBhMTphODo4MDozMDpmOTpiYTpiOTo3NTpjNTphMjoxYjpiZToyMDo3Yzo1ZjoKICAgICAgICAgICAgICAgICAgICBhMjpjZjpiNzphMjo2ODo4MzpiMzoxMTplODoyNTo3Mzo2MzoyNjphNzpiODoKICAgICAgICAgICAgICAgICAgICBjMzpjZDpjODplZTozNjphZjo4ZTo4ZjowZTo5NDowMToyMDpmZjowZTo0MToKICAgICAgICAgICAgICAgICAgICBjYjplZDpmYjo3NDowNToyZDo0NDphOToxNjoxZDo0ODpkNDphNDo3NTo0ZjoKICAgICAgICAgICAgICAgICAgICBlZjo0NDozYTphMDpmMDo1ZTo5ZTo5YjoxOTphZTo4MTozMzpkMDpkMTpmYzoKICAgICAgICAgICAgICAgICAgICA0MTphMTo1OTo5Zjo3MDoxZDphYTo3MzoyNTpiNTpiNjo3NDo2Mzo1NzpjZjoKICAgICAgICAgICAgICAgICAgICAzNTplNzpiZToyNjo1MzoxNDpkNTplNzpiMzpmYToyZDpjYzo5NToyMzo0ODoKICAgICAgICAgICAgICAgICAgICBkOTpkNTozNDplMjowNzoxYjoyNzoyMzpiZTpiODpmNzpiNTpkOTo3MDo1ZDoKICAgICAgICAgICAgICAgICAgICAyOTo4NTo3NToyYjpmYTo0MjpmNTo2Mjo1OTozZjowODo3Njo0Nzo2NjpmNzoKICAgICAgICAgICAgICAgICAgICAxYzpiYzozNzo1MjpiMDo3ODoyNzozNDo3MTo3ZTpiNjozZDowNDpjZDoyMzoKICAgICAgICAgICAgICAgICAgICAzMjphNjoxYTo2NzphNDo4ODoyYTowYTpmMjoxMjphNTo3ODpkYjpiZDpjOToKICAgICAgICAgICAgICAgICAgICA1ZToxMTo4Njo0MDpkMTo0MTplZjpkYzo2Yjo4Zjo1NjpmZDo1MjpkYTo0ZjoKICAgICAgICAgICAgICAgICAgICBiNTpmMDozYTpmZTpjNzoxMDo3ZTpjNDo3OTo2MTo1ZTpkYjo5Zjo4NjpjOToKICAgICAgICAgICAgICAgICAgICBmYjpiNwogICAgICAgICAgICAgICAgRXhwb25lbnQ6IDY1NTM3ICgweDEwMDAxKQogICAgICAgIFg1MDl2MyBleHRlbnNpb25zOgogICAgICAgICAgICBYNTA5djMgQmFzaWMgQ29uc3RyYWludHM6IAogICAgICAgICAgICAgICAgQ0E6RkFMU0UKICAgICAgICAgICAgWDUwOXYzIFN1YmplY3QgS2V5IElkZW50aWZpZXI6IAogICAgICAgICAgICAgICAgMDU6M0Y6RDk6MjE6Rjg6MUE6QjM6NDM6OEQ6QzI6NDA6NzI6OUY6MDE6NDg6MTc6NDE6Nzc6Q0U6MzkKICAgICAgICAgICAgWDUwOXYzIEF1dGhvcml0eSBLZXkgSWRlbnRpZmllcjogCiAgICAgICAgICAgICAgICBrZXlpZDozNTpCRjpBOTozRDo1RjozMzozODowQjowNjo3QzpDQTpFQzo0ODo3QzpCRTo3Njo3MzpCRTpEQjpGRQogICAgICAgICAgICAgICAgRGlyTmFtZTovQ049cmFwaG9lc3RlcgogICAgICAgICAgICAgICAgc2VyaWFsOjhGOjE3OkY1OjJBOjhBOkI0OkQwOjY5CgogICAgICAgICAgICBYNTA5djMgRXh0ZW5kZWQgS2V5IFVzYWdlOiAKICAgICAgICAgICAgICAgIFRMUyBXZWIgU2VydmVyIEF1dGhlbnRpY2F0aW9uCiAgICAgICAgICAgIFg1MDl2MyBLZXkgVXNhZ2U6IAogICAgICAgICAgICAgICAgRGlnaXRhbCBTaWduYXR1cmUsIEtleSBFbmNpcGhlcm1lbnQKICAgICAgICAgICAgWDUwOXYzIFN1YmplY3QgQWx0ZXJuYXRpdmUgTmFtZTogCiAgICAgICAgICAgICAgICBETlM6cmFwaG9lc3RlcgogICAgU2lnbmF0dXJlIEFsZ29yaXRobTogc2hhMjU2V2l0aFJTQUVuY3J5cHRpb24KICAgICAgICAgNTg6M2U6MTE6ZmQ6OWM6ZWQ6MTA6YmQ6NmM6NWE6OWY6NzY6OGY6OTc6MGE6YTY6Mzg6ODI6CiAgICAgICAgIDFhOmYwOmJlOjRiOmU4OjEwOmQ4OjNlOmFhOmFlOjIwOmNiOmMzOjI2OjY1OmU3OmI3OmM3OgogICAgICAgICBjNzo2MToxZTpjNjplMjpjYTpmODo1NTo4ZTpkODoxNjozODphZjo3ZjphZDo3Mjo1MzoxYzoKICAgICAgICAgNmE6MzI6NjE6M2U6ZDM6M2E6NWI6NTg6OTU6NDU6ZGE6MGQ6ZTg6ZjQ6NDM6ZWY6NmY6ZmM6CiAgICAgICAgIDE4OmQxOjA4OjA5OjZlOmQ5OjRmOmQ3OjljOmU2OjliOjAzOmU3OjczOjhkOjExOjNhOjkyOgogICAgICAgICBiMDozYTpjOTpiNDo2MjpmNDphODpiMTphMDo0MzpkMzplODoyZjphZDo5Yjo4ZjoyZjpjZjoKICAgICAgICAgZTA6ZTY6YzE6MWM6MDc6N2E6OWY6YjM6NTI6NWU6MzM6ZWU6MjE6NjY6YTU6MDE6YjA6MzQ6CiAgICAgICAgIDUzOjY5OmRjOjIwOmYyOmY4OmJjOjEyOjJiOjNkOjkyOjM3OjdhOjY3OjZiOmJkOjkzOmZlOgogICAgICAgICA1NTpiMTo5YTo4Yjo5NTpiOTpjMDpkYzpiOToxMTo1MDo5ODoyNjo0MzpkOTpkZTo5ZTo2NzoKICAgICAgICAgZTE6NWE6MmI6YTI6ZmU6YWY6ZDE6ODY6NTQ6N2Y6YzE6NjE6Y2E6ZWQ6NjY6N2Y6YWY6ODQ6CiAgICAgICAgIGFiOjAyOmY5OjBhOmUyOmJkOjFhOjQ1OjgzOmU3OjM1Ojc4OjNkOjAzOmRkOjY4OjkyOjhlOgogICAgICAgICA2YTpkODpjZDoyYToxMzplYzphOTowMjo5OTo1Yzo3ZDplZDowMzo2Mzo5Mzo2MDo1ZTpiYToKICAgICAgICAgNDg6ODM6Zjc6ODA6YzA6YzQ6ZDU6YjM6NjI6NGE6MmM6Njc6NTE6YzA6MmM6MDE6NmU6OWM6CiAgICAgICAgIDNkOmExOjQ2OjcwOjZmOmUwOjIxOmYxOjE5OjE1OjJiOmZmOjQwOjNmOjk4OjdlOjMwOjI3OgogICAgICAgICAxYzplZTo5ZDo3ZQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJRFl6Q0NBa3VnQXdJQkFnSVJBS3FUc1lDcnV1eWVnL2xwbFNUZmxta3dEUVlKS29aSWh2Y05BUUVMQlFBdwpGVEVUTUJFR0ExVUVBd3dLY21Gd2FHOWxjM1JsY2pBZUZ3MHlNakF6TWpjeE9UUXpNVFJhRncweU5EQTJNamt4Ck9UUXpNVFJhTUJVeEV6QVJCZ05WQkFNTUNuSmhjR2h2WlhOMFpYSXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUEKQTRJQkR3QXdnZ0VLQW9JQkFRREc3OVlhUWtKdWtiajF2eVVsMkthTGcvdHRnN1lPYzQ4S01wL0c0dkdHbEJPUwo2MEUxaGIxTjF3ZU9tOHdzMG1lZHlWT0xpTTRST2RqZWNxR29nREQ1dXJsMXhhSWJ2aUI4WDZMUHQ2Sm9nN01SCjZDVnpZeWFudU1QTnlPNDJyNDZQRHBRQklQOE9RY3Z0KzNRRkxVU3BGaDFJMUtSMVQrOUVPcUR3WHA2YkdhNkIKTTlEUi9FR2hXWjl3SGFwekpiVzJkR05YenpYbnZpWlRGTlhucy9vdHpKVWpTTm5WTk9JSEd5Y2p2cmozdGRsdwpYU21GZFN2NlF2VmlXVDhJZGtkbTl4eThOMUt3ZUNjMGNYNjJQUVROSXpLbUdtZWtpQ29LOGhLbGVOdTl5VjRSCmhrRFJRZS9jYTQ5Vy9WTGFUN1h3T3Y3SEVIN0VlV0ZlMjUrR3lmdTNBZ01CQUFHamdhMHdnYW93Q1FZRFZSMFQKQkFJd0FEQWRCZ05WSFE0RUZnUVVCVC9aSWZnYXMwT053a0J5bndGSUYwRjN6amt3UlFZRFZSMGpCRDR3UElBVQpOYitwUFY4ek9Bc0dmTXJzU0h5K2RuTysyLzZoR2FRWE1CVXhFekFSQmdOVkJBTU1DbkpoY0dodlpYTjBaWEtDCkNRQ1BGL1VxaXJUUWFUQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBVEFMQmdOVkhROEVCQU1DQmFBd0ZRWUQKVlIwUkJBNHdESUlLY21Gd2FHOWxjM1JsY2pBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQVdENFIvWnp0RUwxcwpXcDkyajVjS3BqaUNHdkMrUytnUTJENnFyaURMd3labDU3Zkh4MkVleHVMSytGV08yQlk0cjMrdGNsTWNhakpoClB0TTZXMWlWUmRvTjZQUkQ3Mi84R05FSUNXN1pUOWVjNXBzRDUzT05FVHFTc0RySnRHTDBxTEdnUTlQb0w2MmIKankvUDRPYkJIQWQ2bjdOU1hqUHVJV2FsQWJBMFUybmNJUEw0dkJJclBaSTNlbWRydlpQK1ZiR2FpNVc1d055NQpFVkNZSmtQWjNwNW40Vm9yb3Y2djBZWlVmOEZoeXUxbWY2K0Vxd0w1Q3VLOUdrV0Q1elY0UFFQZGFKS09hdGpOCktoUHNxUUtaWEgzdEEyT1RZRjY2U0lQM2dNREUxYk5pU2l4blVjQXNBVzZjUGFGR2NHL2dJZkVaRlN2L1FEK1kKZmpBbkhPNmRmZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K","privatekey":"LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRREc3OVlhUWtKdWtiajEKdnlVbDJLYUxnL3R0ZzdZT2M0OEtNcC9HNHZHR2xCT1M2MEUxaGIxTjF3ZU9tOHdzMG1lZHlWT0xpTTRST2RqZQpjcUdvZ0RENXVybDF4YUlidmlCOFg2TFB0NkpvZzdNUjZDVnpZeWFudU1QTnlPNDJyNDZQRHBRQklQOE9RY3Z0CiszUUZMVVNwRmgxSTFLUjFUKzlFT3FEd1hwNmJHYTZCTTlEUi9FR2hXWjl3SGFwekpiVzJkR05YenpYbnZpWlQKRk5YbnMvb3R6SlVqU05uVk5PSUhHeWNqdnJqM3RkbHdYU21GZFN2NlF2VmlXVDhJZGtkbTl4eThOMUt3ZUNjMApjWDYyUFFUTkl6S21HbWVraUNvSzhoS2xlTnU5eVY0UmhrRFJRZS9jYTQ5Vy9WTGFUN1h3T3Y3SEVIN0VlV0ZlCjI1K0d5ZnUzQWdNQkFBRUNnZ0VBV0loMzhpdTJ3TnBkUkJDVENhckhRNk96QzJQb2E3b0YySFg3SVZueVB3QTcKVGRFZ3JoOGN4ajJDQVhkWWdFSUxGdTk0SE1yL1dpOHlVcDBWVUpYc05kZGhuZ1ljUk5oeVFLZVhIM1lMOHhOWgphQWkyVWdtNE5FQkg4NWNPWEl2NGw3WFhMRUZ4QVBsTE5sZ0hwQjRuUmxDdks3Qm1tRWJBcHM2b3ZSQis2V3JVCkRBWTc0UDNPTi9EMmxyczVNSzlCdlA1d0FsZml1L0x3MTV4NE1UVEE2MkxHNU1remUxV2d0VGtXdnN0VUNXZUUKYW9zQ21tbVhwUGJvR2ZzRXcvSGpWdnZ6UFNKMDhid0U0Mlk2VUFtMGgzWjdMQ1o5ajJtazBsS2NpdStzYndoKwpGL3VvZHdMc2d3bGErNGFGN3g4ZW9rb0RCeVRjVSt1VUVaZWR3MEVKb1FLQmdRRC92ejhFTkM3Q3pSR2VBWjR0Cjhobkdnd2FjbXRjRmVHTHVWVG5iY3ZIZ2EwbVpabk5jdHdpRVlHMm9CYWtkWFcwTmN5WU1tQWlFZXczNTk2Q3QKakxzY0ViSEhMYmV4OGNHWTZlM3gwRFhPTkVGYlBNUnFUTWtIZytIS2tHbWxES3EzUkNxc2RzYnd3T3EyaEd6dApCNnp2SHNuUXlXeEtnMlE2bXVhckpXaUpYd0tCZ1FESElqVEUrQ2pTWkVvZ0E3dG1zN1NkR0cyY0NjNnB0RWRrCmZPZWFGVzJPWDlia2JjakxXcm9zRmpSVm1nbVRXSFZNcnBmR3p5aVBKTWNtanZxbnQzYklVU2JXK2xKMWdZL0sKSTkyL3Q0K09PRTRUL0xYZ09Hc2lOajh1R3ZTMkt2VnNXOE4yMW8vMkE3TklDcEZlTlFuRnFpcW1vazRzV1FjdAprUCtVc3lBMHFRS0JnRUViUXNPak5UUktXRzNOSTZPMnVuRWE4aGYwSTBFMVFKcEVBQktwMUlHNVRtZEsrWnRrCnpUcEdBaVNBTEdsWlcyWE5KcWFXSGJUOFRyYVFIOHVPeENPRkxhanpMb3lTYXlLdWl2REFmTEllQTNWaXB1NFkKMWlTZm9sK2JIQW4waTVGVVBUamlsQXErVWdKYy9BM3JvazdObTdzWFRBWThKTXYybXpwK3Izb3BBb0dBZit1bApZbkxZSm05dWZxcG5GRTZVMCtZQlk1K1pOc01zcVl6amFzUWhJTGpJWHUxM2M4clFsY21kek8rcS94QndLZFp1CmdiUktKY3BHZEtxY3NtalUwVkh3VldGdzN6TmZuMGJ6Q0ZsdXlybTR6bllraitrdVNVZjN4akppeVROSGZWaGwKZEUzWkpQeXppcS9mT2xsdjhaNml6M0NzTHlqeHgzL0I3MUF5ZkNFQ2dZQk5KckJEdnRSZDRCbmVXQjI5Mk84MQpBU0JpWnNPaHFDMnhSWWg1YnYyVFA2clpQd0h0cGV5MmJEK21iQVpLd003TDRKeHJxK3c0aERTN2EwRlowUm1rCi9yRlpvSjR3MDZWNGM2ZndyZG9WZmRvWE5zNkViQmd1ekxab0YyOFNUc3pOZGhFelJkdFNyWWxlalM1UnVDV2UKbUJ1L0g1d1lBNFFtUU9hRzMranFVZz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K","certificatechain":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURNakNDQWhxZ0F3SUJBZ0lKQUk4WDlTcUt0TkJwTUEwR0NTcUdTSWIzRFFFQkN3VUFNQlV4RXpBUkJnTlYKQkFNTUNuSmhjR2h2WlhOMFpYSXdIaGNOTWpJd016STNNVGswTXpBMVdoY05Nekl3TXpJME1UazBNekExV2pBVgpNUk13RVFZRFZRUUREQXB5WVhCb2IyVnpkR1Z5TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCCkNnS0NBUUVBdUlqRXJzc0hHSFR3TmNFbjhVTmlKQjErQ0lzL2Q2aklVaXRjUlFJcEhseVJPYzMxaDNyOGlkV0oKK2pGNkFSSndXQThIcmRKYTVCTFhYK3BMWWtMblQ1V2xBVjZkNi9FT2xoUDlCM2tyNHE2ODB0TFhUM3J3UitOdAo0ZTZ0MnUzbjFIS0tsMGM0U25xRGY2b1NjRzE5SGh5OWcvbmp6eFpLVXhZd21tWDRZZXdsSnZNSXZ0VnA5M2JFClQ1MjdJdk5lcFN4MXBBTmhtLzVTRW1zQ3MwQ2pENmZZOXNrcWUra3piZE1TOFhNZlZQYkVXUzdjcG9lZERpSFEKdTVRQVhjSmxnRUVCTjMvbG5JZEpxQ0xQOEFTV2hWd3puSmNEemc5UEcrTlZ4S1A1MHV0bDdROHdsd0Z0R2d4UAp5REhvamNsbVBtQ291UmdHb2RrMnJBQ0lYME9PTFFJREFRQUJvNEdFTUlHQk1CMEdBMVVkRGdRV0JCUTF2Nms5Clh6TTRDd1o4eXV4SWZMNTJjNzdiL2pCRkJnTlZIU01FUGpBOGdCUTF2Nms5WHpNNEN3Wjh5dXhJZkw1MmM3N2IKL3FFWnBCY3dGVEVUTUJFR0ExVUVBd3dLY21Gd2FHOWxjM1JsY29JSkFJOFg5U3FLdE5CcE1Bd0dBMVVkRXdRRgpNQU1CQWY4d0N3WURWUjBQQkFRREFnRUdNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUN6YXU1QlNnSituZy92Cnd2SHVDTnEyZWg5c1M1M3pmVUlQeTZqTUZrZHprelVZTmI1WjFRK1hjb21GbU9xOVVmaWcxN2dZdUR3WC9nMlMKVklDMVJDdWxwVTNORnNLOEhrSDdjdVFPOGNjSnlWc3JtUndPSFhabmtwTnBoYXI4RFQvSjU5d3FNU09ZZUJQYgpuQU41T0piaUF0NlRBNmRsUXJidkFvWG04dXdHMjFSU1N1VHQ5UElsY3NGallQazhiQWJ0dXdldEVnYjVuNkhoClhhczA1S0dteENmZDZxNHAxYUxITkVpNTVSejg0bEVsVHVNZlA0ZEwyZjIzUnFncmpEQmNDRmEwN1owZHJNdjcKbERYNEovaVpXY08zWXJJWXppcVg5M015UzNSUCtrYXAvV0dIYlZDcWtpZ2lTODZwQkY1NDh3OWxXQ0xJai9kTgozRTI2V24zNgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="}}`
// yeah the string is long lol
var body ResponseBody
if err := json.Unmarshal([]byte(mystring), &body); err != nil {
fmt.Println(fmt.Errorf("failed unmarshaling response | %s", err.Error()))
}
fmt.Println(body.Error.ErrorMessage)
certChain, err := base64.StdEncoding.DecodeString(mystring)
if err != nil {
fmt.Println(err.Error())
}
fmt.Println(certChain)
}
type PkiGenerationInput struct {
TeacherUsername string `json:"teacherusername"`
}
type Response struct {
Headers ResponseHeaders `json:"headers"`
Body ResponseBody `json:"body"`
}
type ResponseHeaders struct {
ContentType string `json:"Content-Type"`
}
type ResponseBody struct {
PkiData ParsablePkiData `json:"pkidata"`
Error struct {
ErrorMessage string `json:"errormessage"`
ErrorType string `json:"errortype"`
} `json:"error"`
}
type ParsablePkiData struct {
Certificate string `json:"certificate"`
PrivateKey string `json:"privatekey"`
CertificateChain string `json:"certificatechain"`
}
Here is the output
errormessagetest
illegal base64 data at input byte 0
[]
the fact I can read the errormessagetest shows that the unmarshalling kinda works, so that's weird.
I checked for any unexported fields but we can clearly see they are all capitalized. I also reduced the string size "just to see" and it didn't change anything.
Answer to synthetize all of the comments :
First of all, my "dumb mistake" was because I tried to decode the wrong variable :
// mystring needs to be replaced by body.PkiData.Certificate
base64.StdEncoding.DecodeString(mystring)
But the research led us to discover that the json.Unmarshal() function decodes base64 by itself when the result type matches what the declared type. Given the fact the encoded data was a []byte, I just replaced the string type by a []byte in the struct.
That allows to create a much more simple version of the previous code :
type ResponseBody struct {
PkiData PkiData `json:"pkidata"`
}
type PkiData struct {
Certificate []byte
PrivateKey []byte
CertificateChain []byte
}
var body ResponseBody
if err := json.Unmarshal(rawResp.Payload, &body); err != nil {
return PkiData{}, fmt.Errorf("failed unmarshaling response | %s", err.Error())
}
What I want to do is commented:
type foo struct {
Message string `json:"message"`
}
func bar() {
//The "message" field contains a bool type which does not
//match the equivalent "message" field in foo, a string type
jsonData := byte[]("{
\"message\": true
}")
var baz foo
//Because the type of "message" in the json bytes is
//bool and not a string, put "" inside baz.Message
json.Unmarshal(jsonData, &baz)
}
How do I Unmarshal the json byte array, then only populate the particular field if the field matches the type in the json byte array field? And if the field does type does not match the json byte array field type, put in a placeholder value of nil, "" etc. ?
There are many ways to handle this, once you fix your question to something that can be answered. The one I like is to unmarshal to a variable of type interface{}, which you can then inspect:
package main
import (
"encoding/json"
"fmt"
)
type foo struct {
Message interface{} `json:"message"`
}
func bar() {
//The "message" field contains a bool type which does not
//match the equivalent "message" field in foo, a string type
jsonData := []byte(`{
"message": true
}`)
var baz foo
//Because the type of "message" in the json bytes is
//bool and not a string, put "" inside baz.Message
err := json.Unmarshal(jsonData, &baz)
fmt.Printf("unmarhal error is: %v\n", err)
if err == nil {
fmt.Printf("baz.Message is now: %T = %v\n", baz.Message, baz.Message)
}
}
func main() {
bar()
}
(Go Playground link)
It should now be fairly obvious how to switch on the type (after decoding) and see if what you got is what you want. If so, use it. If not, use your default. If necessary, decode the incoming json to more-generic Go types first, then fill in the specific type you really want to handle.
The Unmarshaler interface in the encoding/json package allows you to have full control over how the data is decoded into your types.
You only need to implement one method on your type - UnmarshalJSON(data []byte).
In the example below, I've declared a temporary anonymous type in my UnmarshalJSON method and decoded the json into an empty interface.
I can then type assert the interface into a string, and on success I set the Message field on my original Foo type. We don't need to handle the failure case, since strings in Go have a default value of "".
Here's a working example.
type Foo struct {
Message string
}
func (this *Foo) UnmarshalJSON(data []byte) error {
raw := struct {
Message interface{} `json:"message"`
}{}
err := json.Unmarshal(data, &raw)
if err != nil {
return err
}
if msgString, ok := raw.Message.(string); ok {
this.Message = msgString
}
return nil
}
I am struggling with deserializing a integer into a string struct field.
The struct field is a string and is expected to be assignable from users of my library. That's why I want it to be a string, since for the purpose of writing it to the database I actually don't care about the value inside.
The users can supply text, but some just assign integers.
Consider this struct:
type Test struct {
Foo string
}
Sometimes I end up with a JSON value that is valid but won't deserialize into the struct due to the Foo field being a integer instead of a string:
{ "foo": "1" } // works
{ "foo": 1 } // doesn't
json.Unmarshal will blow up with the following error:
json: cannot unmarshal number into Go struct field test.Foo of type string
See the reproduction: https://play.golang.org/p/4Qau3umaVm
Now in every other JSON library (in other languages) I have worked in so far, if the target field is a string and you get a integer the deserializer will usually just wrap the int in a string and be done with it. Can this be achieved in Go?
Since I can't really control how the data comes in I need to make json.Unmarshal unsensitive to this - the other solution would be to define Foo as interface{} which needlessly complicates my code with type assertions etc..
Any ideas on how to do this? I basically need the inverse of json:",string"
To handle big structs you can use embedding.
Updated to not discard possibly previously set field values.
func (t *T) UnmarshalJSON(d []byte) error {
type T2 T // create new type with same structure as T but without its method set!
x := struct{
T2 // embed
Foo json.Number `json:"foo"`
}{T2: T2(*t)} // don't forget this, if you do and 't' already has some fields set you would lose them
if err := json.Unmarshal(d, &x); err != nil {
return err
}
*t = T(x.T2)
t.Foo = x.Foo.String()
return nil
}
https://play.golang.org/p/BytXCeHMvt
You can customize how the data structure is Unmarshaler by implementing the json.Unmarshaler interface.
The simplest way to handle unknown types is to unnmarshal the JSON into an intermediate structure, and handle the type assertions and validation during deserialization:
type test struct {
Foo string `json:"foo"`
}
func (t *test) UnmarshalJSON(d []byte) error {
tmp := struct {
Foo interface{} `json:"foo"`
}{}
if err := json.Unmarshal(d, &tmp); err != nil {
return err
}
switch v := tmp.Foo.(type) {
case float64:
t.Foo = strconv.Itoa(int(v))
case string:
t.Foo = v
default:
return fmt.Errorf("invalid value for Foo: %v", v)
}
return nil
}
https://play.golang.org/p/t0eI4wCxdB
I am trying to unmarshal JSON into a struct. However, the struct has a field with a tag. Using reflection, and I try to see if the tag has the string "json" in it. If it does, then the json to unmarshal should simply be unmarshaled into the field as a string.
Example:
const data = `{"I":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
S string `sql:"type:json"`
}
Problem is simple - unmarshal "S" in the json as a string into the struct A.
This is how far I have come. But I am stuck here.
http://play.golang.org/p/YzrhjuXxGN
This is the go way of doing it - no reflection requred. Create a new type RawString and create MarshalJSON and UnmarshalJSON methods for it. (playground)
// RawString is a raw encoded JSON object.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawString string
// MarshalJSON returns *m as the JSON encoding of m.
func (m *RawString) MarshalJSON() ([]byte, error) {
return []byte(*m), nil
}
// UnmarshalJSON sets *m to a copy of data.
func (m *RawString) UnmarshalJSON(data []byte) error {
if m == nil {
return errors.New("RawString: UnmarshalJSON on nil pointer")
}
*m += RawString(data)
return nil
}
const data = `{"i":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
S RawString `sql:"type:json"`
}
func main() {
a := A{}
err := json.Unmarshal([]byte(data), &a)
if err != nil {
log.Fatal("Unmarshal failed", err)
}
fmt.Println("Done", a)
}
I modified the implementation of RawMessage to create the above.
The problem here is that you are using one encoding format for two protocols and probably there is something wrong in your model.
That is a valid Json payload and should be handled as such. One trick that you can use is to create
another field to handle the "string" json and one to handle the "json struct".
See this modified example: I first unmarshal json and then marshal back to json to create the final string to upload to the database. One field is used for unmarshaling and the other to communicate with the DB.
package main
import(
"fmt"
"encoding/json"
)
const data = `{"i":3, "S":{"phone": {"sales": "2223334444"}}}`
type A struct {
I int64
Sjson struct {
Phone struct {
Sales string `json:"sales"`
} `json:"phone"`
} `json:"S", sql:"-"`
S string `sql:"type:json",json:"-"`
}
func main() {
msg := A{}
_ = json.Unmarshal([]byte(data), &msg)
data, _ := json.Marshal(msg.Sjson)
msg.S = string(data)
fmt.Println("Done", msg)
}
Looks like the problem is that s interface{} in your code was not addressable. For Value.SetString the Value has to be addressable and with Kind String. you can check the documentation for it - http://golang.org/pkg/reflect/#Value.SetString
How i understand it SetString would not change the value in a, since you are only working with interface s. in Laws of Reflection you can find "reflect.ValueOf is a copy of x, not x itself"(3rd Law).
To make your code work I made some type assertions, and I used reflect.ValueOf on a pointer to asserted struct.
To check if Value is settable or addressable you can use Value.CanSet ad Value.CanAddr
working code: http://play.golang.org/p/DTriENkzA8
No idea whether its correct way to do this
I have struct
type tySurvey struct {
Id int64 `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
I do json.Marshal write JSON bytes in HTML page. jQuery modifies name field in object and encodes object using jQueries JSON.stringify and jQuery posts string to Go handler.
id field encoded as string.
Sent: {"id":1} Received: {"id":"1"}
Problem is that json.Unmarshal fails to unmarshal that JSON because id is not integer anymore.
json: cannot unmarshal string into Go value of type int64
What is best way to handle such data? I do not wish to manually convert every field. I wish to write compact, bug free code.
Quotes is not too bad. JavaScript does not work well with int64.
I would like to learn the easy way to unmarshal json with string values in int64 values.
This is handled by adding ,string to your tag as follows:
type tySurvey struct {
Id int64 `json:"id,string,omitempty"`
Name string `json:"name,omitempty"`
}
This can be found about halfway through the documentation for Marshal.
Please note that you cannot decode the empty string by specifying omitempty as it is only used when encoding.
use json.Number
type tySurvey struct {
Id json.Number `json:"id,omitempty"`
Name string `json:"name,omitempty"`
}
You could also create a type alias for int or int64 and create a custom json unmarshaler
Sample code:
Reference
// StringInt create a type alias for type int
type StringInt int
// UnmarshalJSON create a custom unmarshal for the StringInt
/// this helps us check the type of our value before unmarshalling it
func (st *StringInt) UnmarshalJSON(b []byte) error {
//convert the bytes into an interface
//this will help us check the type of our value
//if it is a string that can be converted into a int we convert it
///otherwise we return an error
var item interface{}
if err := json.Unmarshal(b, &item); err != nil {
return err
}
switch v := item.(type) {
case int:
*st = StringInt(v)
case float64:
*st = StringInt(int(v))
case string:
///here convert the string into
///an integer
i, err := strconv.Atoi(v)
if err != nil {
///the string might not be of integer type
///so return an error
return err
}
*st = StringInt(i)
}
return nil
}
func main() {
type Item struct {
Name string `json:"name"`
ItemId StringInt `json:"item_id"`
}
jsonData := []byte(`{"name":"item 1","item_id":"30"}`)
var item Item
err := json.Unmarshal(jsonData, &item)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", item)
}