2014-09-10 92 views
10

Belirli bir yapıyı veritabanım içinde JSON alanı olan bir veritabanında depolamak istiyorum.Golang JSON'u Postgresql'e Kaydetme

type Comp struct { 
    CompId    int64   `db:"comp_id" json:"comp_id"` 
    StartDate   time.Time  `db:"start_date" json:"start_date"` 
    EndDate    time.Time  `db:"end_date" json:"end_date"` 
    WeeklySchedule  json.RawMessage `db:"weekly_schedule" json:"weekly_schedule"` 
} 

tablo için şema geçerli: Projemde sqlx ve pq/lib sürücüyü kullanıyorum ve şu yürütmez

CREATE TABLE IF NOT EXISTS Tr.Comp(
    comp_id     SERIAL, 
    start_date    timestamp NOT NULL, 
    end_date    timestamp NOT NULL, 
    weekly_schedule   json NOT NULL, 
    PRIMARY KEY (comp_id) 
); 

. Bunun yerine bir nil işaretçisi olduğunu söyleyen panik. Ben şemadan weekly_schedule kaldırıp fikstürü şeyin yolunda çalıştırdığınızda DB küresel *sqlx.DB yapı

tx := DB.MustBegin() 

    compFixture := Comp{ 
     StartDate:   time.Now(), 
     EndDate:    time.Now().AddDate(1, 0, 0), 
     WeeklySchedule:  json.RawMessage([]byte("{}")), 
    } 
    _, err = tx.NamedExec(
     `INSERT INTO 
      Tr.Comp(comp_id, 
       start_date, end_date, weekly_schedule) 
      VALUES (DEFAULT, 
       :start_date, :end_date, :weekly_schedule) 
      RETURNING comp_id;`, compFixture) 
    if err != nil { 
     t.Fatal("Error creating fixture.", err) 
    } 

olduğunu. Ama bir sebepten dolayı, bu alan ne zaman dahil olursa, program panik. Hem DB şema hem de Git yapısında weekly_schedule alanını nasıl tanımlamalıyım konusunda bir fikrim var mı?

cevap

8

sqlx Eğer JSONText

+0

evet için

doc gerekenleri yapacağız github.com/jmoiron/sqlx/types bir tür JSONText sahiptir. Bu tam olarak aradığım şey. Teşekkürler – moesef

+0

kısa bir süre önce 'JSONText' olarak yeniden adlandırıldı. Https://github.com/jmoiron/sqlx/commit/4301d72cf9192e9d0a830370e31323dce943e005 –

+0

@HarryMoreno Cevabımı güncelledim. Bana bildirdiğiniz için teşekkürler. – jmaloney

2

Bu sorunun ne kadar temiz olduğunu bilmiyorum ama kendi veri türümü JSONRaw yapıyorum. DB sürücüsü bir []btye olarak görür, ancak yine de Go kodunda bir json.RawMessage gibi ele alınabilir.

type JSONRaw json.RawMessage 

func (j JSONRaw) Value() (driver.Value, error) { 
    byteArr := []byte(j) 

    return driver.Value(byteArr), nil 
} 

func (j *JSONRaw) Scan(src interface{}) error { 
    asBytes, ok := src.([]byte) 
    if !ok { 
     return error(errors.New("Scan source was not []bytes")) 
    } 
    err := json.Unmarshal(asBytes, &j) 
    if err != nil { 
     return error(errors.New("Scan could not unmarshal to []string")) 
    } 

    return nil 
} 

func (m *JSONRaw) MarshalJSON() ([]byte, error) { 
    return *m, nil 
} 

func (m *JSONRaw) UnmarshalJSON(data []byte) error { 
    if m == nil { 
     return errors.New("json.RawMessage: UnmarshalJSON on nil pointer") 
    } 
    *m = append((*m)[0:0], data...) 
    return nil 
} 

Bu encoding/json kütüphanesinden MarshalJSON ve UnmarshalJSON ait kopyala yapıştır reimplementation olduğunu.

json.RawMessage is a raw encoded JSON object. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding. 

eğer log.Printf ("% #", renkler) json nesnesi unmarshalling sonra görebiliriz json.RawMessage paket json sağlanan örnekte 'Nokta: go belgelerinden

0

'-arma biçimli değil ancak renk biçimi düzeltilinceye ve' Nokta 'açıkça anlaşılmamış olana kadar [] bayt biçiminde bırakılır.

DB'ye koymadan önce WeeklySchedule unmarshal gibi bir şey denediniz mi?