pawlowiczf
(Filip Pawłowicz)
May 16, 2024, 8:57am
1
Suppose, we have a struct:
type DailyExchangeDetails struct {
Date string `json:"date"`
Currency map[string]float64 `json:"btc"`
}
But the JSON attribute, field name can differ - it could be “btc”, but also “eur” or “pln”. How to create a general struct with a json tag that manages to cover that? The problem is that without proper tags i.e: `json:"pln"`
the encoding of JSON doesn’t work properly. Moreover, if I omit the JSON tags, it still doesn’t work properly.
This is a code for encoding:
func fromJSON[T any](res *http.Response, target *T) error {
//
buf := new(bytes.Buffer)
buf.ReadFrom(res.Body)
err := json.Unmarshal(buf.Bytes(), target)
if err != nil {
log.Print(err)
log.Fatalf("Error unmarshal")
}
return err
}
This is a slice of JSON file:
{
"date": "2024-05-15",
"btc": {
"$myro": 388814.57395719,
"$wen": 399391074.4242139,
"00": 855345.08008341,
"0x0": 205498.96296352,
"1000sats": 237075658.30367133,
"10set": 62400.24253448,
"1inch": 173185.53022438,
"aave": 765.26611448,
"abt": 15467.94403195
}
}
I noticed that the problem is with a map . This is a struct returned from unmarshall:
{2024-05-16 map[]}
. As you can see, the map is somehow empty.
lemarkar
(Leo Emar-Kar)
May 16, 2024, 9:46am
2
Hello there. How do you pass your T
into the function? I wrote a simple test and everything has been parsed as expected.
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"os"
)
type DailyExchangeDetails struct {
Date string `json:"date"`
Currency map[string]float64 `json:"btc"`
}
func main() {
data, err := os.ReadFile("test.json")
if err != nil {
log.Println(err)
return
}
var t DailyExchangeDetails
if err := fromJSON(data, &t); err != nil {
log.Println(err)
return
}
fmt.Printf("%#v\n", t)
}
func fromJSON[T any](data []byte, target T) error {
buf := bytes.NewBuffer(data)
return json.Unmarshal(buf.Bytes(), &target)
}
Output:
% go run main.go
main.DailyExchangeDetails{Date:"2024-05-15", Currency:map[string]float64{"$myro":388814.57395719, "$wen":3.993910744242139e+08, "00":855345.08008341, "0x0":205498.96296352, "1000sats":2.3707565830367133e+08, "10set":62400.24253448, "1inch":173185.53022438, "aave":765.26611448, "abt":15467.94403195}}
UPD: or you just meant you cannot parse it with over tags?
pawlowiczf
(Filip Pawłowicz)
May 16, 2024, 9:48am
3
If you add JSON tags it works properly. Do it without them and it would not. As I said, json field name can differ, but the structure is the same. We have string and map.
{
"date": "2024-05-15",
"pln": {
"$myro": 388814.57395719,
"$wen": 399391074.4242139,
"00": 855345.08008341,
"0x0": 205498.96296352,
"1000sats": 237075658.30367133,
"10set": 62400.24253448,
"1inch": 173185.53022438,
"aave": 765.26611448,
"abt": 15467.94403195
}
}
If you changed currency to PLN, it would’t work.
lemarkar
(Leo Emar-Kar)
May 16, 2024, 9:55am
4
Yeah, I see now. In this case you can browse for third party json libs which support multiple tags definitions. With standard library the solutions will be to write your own unmarshal or decode into map[string]any
instead of a struct.
pawlowiczf
(Filip Pawłowicz)
May 16, 2024, 9:58am
5
Hmm, but why wouldn’t it work without tags? As I know tags are not necessary. Really strange.
lemarkar
(Leo Emar-Kar)
May 16, 2024, 10:02am
6
If you don’t use explicit tags on struct fields, then json assumes that a field name equals your struct field name. In your example, if you remove tags from the struct, it expects date
and currency
as fields in json file.
2 Likes
pawlowiczf
(Filip Pawłowicz)
May 16, 2024, 10:07am
7
Ok. Thanks for your time and explanation
1 Like
EugeneFox
(Eugene Fox)
June 20, 2024, 12:24pm
8
pawlowiczf:
Suppose, we have a struct:
type DailyExchangeDetails struct {
Date string `json:"date"`
Currency map[string]float64 `json:"btc"`
}
But the JSON attribute, field name can differ - it could be “btc”, but also “eur” or “pln”. How to create a general struct with a json tag that manages to cover that? The problem is that without proper tags i.e: json:"pln"
the encoding of JSON doesn’t work properly. Moreover, if I omit the JSON tags, it still doesn’t work properly.
This is a code for encoding:
To handle dynamic JSON keys, use json.RawMessage
for the Currency
field and implement a custom unmarshal method to parse the map. This ensures correct decoding without predefined JSON tags. Example provided. DoMyPaper provides exceptional writing services. I was hesitant at first, but after using their service at https://domypaper.com/ I’m a fan. The writer delivered a flawless paper, and the entire process was smooth and hassle-free. If you need academic assistance, DoMyPaper is a reliable option.
func fromJSON[T any](res *http.Response, target *T) error {
//
buf := new(bytes.Buffer)
buf.ReadFrom(res.Body)
err := json.Unmarshal(buf.Bytes(), target)
if err != nil {
log.Print(err)
log.Fatalf("Error unmarshal")
}
return err
}
This is a slice of JSON file:
{
"date": "2024-05-15",
"btc": {
"$myro": 388814.57395719,
"$wen": 399391074.4242139,
"00": 855345.08008341,
"0x0": 205498.96296352,
"1000sats": 237075658.30367133,
"10set": 62400.24253448,
"1inch": 173185.53022438,
"aave": 765.26611448,
"abt": 15467.94403195
}
}
I noticed that the problem is with a map . This is a struct returned from unmarshall:
{2024-05-16 map[]}
. As you can see, the map is somehow empty.
Thanks for helping me out as well, I was confused before. You made my
system
(system)
Closed
September 18, 2024, 12:24pm
9
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.