2014-12-15 35 views
7

Tôi đang phát triển một trang web bằng cách sử dụng Go và kết nối nó với Tìm kiếm Đàn hồi. Trong Tìm kiếm Đàn hồi, tôi có thể có các trường động cho các loại chỉ mục. Khi tôi đọc một tài liệu từ Elastic Search, nó sẽ trả về một đối tượng JSON như là kết quả, có thể bao gồm các trường có tên động (hoặc các trường do người dùng xác định).Cách ánh xạ các đối tượng JSON với các trường động tới các cấu trúc Go

Tôi có thể nhận được kết quả JSON và unmarshal nó vào một cấu trúc Go, nhưng tôi không biết cách tốt nhất để giữ cho các trường động như một phần của cấu trúc Go là gì.

Đây là những gì tôi đang làm. Ví dụ, nếu tôi nhận được một tài liệu cho một Liên từ đàn hồi tìm kiếm nó có thể trông giống như thế này:

{ 
    "EmailAddress": "[email protected]", 
    "Name": "Test Contact", 
    "Phone": "17894785236", 
    "City": "San Francisco", 
    "State": "California" 
} 

Và struct Go cho Liên là:

type Contact struct { 
    EmailAddress   string 
    Name     string 
    Phone     string 
    CustomFields   map[string]interface{} 
} 

Và tôi thực hiện MarshalerUnmarshaler để ghi đè cách đối tượng được So sánh và Không được sửa đổi.

func (c *Contact) MarshalJSON() ([]byte, error) { 
    contactMap := make(map[string]interface{}) 
    contactMap["EmailAddress"] = c.EmailAddress 
    contactMap["Name"] = c.Name 
    contactMap["Phone"] = c.Phone 

    for k, v := range c.CustomFields { 
     contactMap[k] = v 
    } 

    return json.Marshal(contactMap) 
} 

func (c *Contact) UnmarshalJSON(data []byte) error { 
    var contactMap map[string]interface{} 

    if c == nil { 
     return errors.New("RawString: UnmarshalJSON on nil pointer") 
    } 

    if err := json.Unmarshal(data, &contactMap); err != nil { 
     return err 
    } 

    c.EmailAddress = contactMap["EmailAddress"].(string) 
    c.Name = contactMap["Name"].(string) 
    c.Phone = contactMap["Phone"].(string) 

    for key, val := range contactMap { 
     if key != "EmailAddress" && key != "Name" && Key != "Phone" { 
      c.CustomFields[key] = value 
     } 
    } 

    return nil 
} 

Đây có phải là cách tốt nhất để làm điều này không? Bạn muốn giới thiệu gì?

+1

Trường sẽ ngẫu nhiên như thế nào? Có khả năng hoàn toàn ngẫu nhiên? Nếu vậy, những gì bạn có ở trên là đặt cược tốt nhất của bạn. Tuy nhiên, nếu bạn có thể giới hạn các phần động vào một cấu trúc cụ thể, thì bạn có thể mô hình thêm các cấu trúc xung quanh phần đó và loại bỏ chúng một cách riêng biệt sau khi bạn đã xác định chúng là gì. –

+0

Có, chúng sẽ là ngẫu nhiên. Chúng sẽ không theo bất kỳ cấu trúc nào, chúng sẽ là các trường do người dùng định nghĩa. Tôi sẽ để nó như vậy. – user1845791

Trả lời

3

Chỉ cần thêm chút dọn dẹp

var contactMap map[string]interface{} 

if c == nil { 
    return errors.New("RawString: UnmarshalJSON on nil pointer") 
} 

if err := json.Unmarshal(data, &contactMap); err != nil { 
    return err 
} 

for key, val := range contactMap { 
    switch key { 
     case "EmailAddress": 
      c.EmailAddress = val.(string) 
     case "Name": 
      c.Name = val.(string) 
     case "Phone": 
      c.Phone = val.(string) 
     default: 
      c.CustomFields[key] = val 
     } 
    } 
} 
+0

Cảm ơn bạn. Tôi sẽ thực hiện thay đổi này. – user1845791

+0

Bạn được chào đón. –

4

Theo Simon đã chỉ ra trong bình luận, sử dụng một lớn bản đồ [chuỗi] giao diện {} không phải là lý tưởng nếu cấu trúc của json là cố định. Cách tốt nhất là sử dụng cấu trúc và unmarshall nó bằng cách sử dụng http://golang.org/pkg/encoding/json/#Unmarshal. (tham khảo ví dụ: http://play.golang.org/p/cDTe8x4xLk)

Nhưng đối với đốm màu đốm lớn, cấu trúc không được biết trước, việc triển khai của bạn hoạt động hoàn hảo.

chỉnh sửa: đã thêm liên kết vào ví dụ

Các vấn đề liên quan