3

I have a json object sent from a mobile application, looks like this:

{
    "product_id": "0123456789",
    "name": "PRODUCT_NAME",
    "manufacturer": "PRODUCT_MANUFACTURER",
    "image_url": "IMAGE_URL",
    "additional_info": "",
    "store_id": "STORE_ID",
    "store_name": "STORE_NAME",
    "owner_id": "OWNER_ID",
    "quantities": {
        "1000": 10.0,
        "1500": 12.0,
    }
}

The key value in quantities is a for example, can be grams, and the value is a representes a price. So for example, 1000 grams of rice will cost 10$, and 1500 grams of rice will cost 12.0$ (as a sale or something)

I have a Model Object in my Go code, that has the quantities filed as map[int]float32 I'm trying to find a way to insert this map into a PostgreSQL database I have, but can't figure out how.

This is my Go Model:

type Product struct {
    ID             string          
    UUID           string          
    Name           string         
    Manufacturer   string         
    ImageURL       string         
    AdditionalInfo string          
    StoreID        string         
    StoreName      string          
    OwnerID        string          
    Quantities     map[int]float32
}

I read about JSONB but won't it return a json when I retrieve the data? I need it to return a map[int]float32 and not json.

0

1 Answer 1

2

You need to implement driver.Valuer and sql.Scanner interface for save as JSONB

The driver.Valuer interface, such that it marshals the object into a JSON byte slice that can be understood by the database.

The sql.Scanner interface, such that it unmarshals a JSON byte slice from the database into the struct fields.

And for json Marshal you need to convert map[int]float32 into map[string]float32

type cusjsonb map[int]float32

// Returns the JSON-encoded representation
func (a cusjsonb) Value() (driver.Value, error) {
    // Convert to map[string]float32 from map[int]float32 
    x := make(map[string]float32)
    for k, v := range a {
       x[strconv.FormatInt(int64(k), 10)] = v
    }
    // Marshal into json 
    return json.Marshal(x)
}

// Decodes a JSON-encoded value
func (a *cusjsonb) Scan(value interface{}) error {
    b, ok := value.([]byte)
    if !ok {
        return errors.New("type assertion to []byte failed")
    }
    // Unmarshal from json to map[string]float32
    x := make(map[string]float32)
    if err := json.Unmarshal(b, &x); err != nil {
       return err
    }
    // Convert to map[int]float32 from  map[string]float32
    *a = make(cusjsonb, len(x))
    for k, v := range x {
      if ki, err := strconv.ParseInt(k, 10, 32); err != nil {
         return err
      } else {
         (*a)[int(ki)] = v
      }
    }
    return nil
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.