2012-06-20 34 views
40

Có lý do kỹ thuật nào khiến các trường chưa được xuất bản không được bao gồm bởi mã hóa/json không? Nếu không và đó là một quyết định tùy ý có thể có thêm một tùy chọn cửa sau (nói '+') để bao gồm mặc dù không được báo cáo?JSON và xử lý các trường chưa được xuất hiện

Yêu cầu mã máy khách xuất để có chức năng này cảm thấy không may, đặc biệt nếu trường hợp thấp hơn cung cấp đóng gói hoặc quyết định sắp xếp cấu trúc muộn hơn nhiều so với thiết kế của chúng.

Mọi người xử lý vấn đề này như thế nào? Chỉ cần xuất tất cả mọi thứ?

Ngoài ra, không xuất các tên trường khiến bạn khó theo dõi các thành ngữ được đề xuất. Tôi nghĩ rằng nếu một cấu trúc X có trường Y, bạn không thể có phương thức truy cập Y(). Nếu bạn muốn cung cấp quyền truy cập giao diện cho Y, bạn phải đưa ra tên mới cho trình khởi động và không có vấn đề gì bạn sẽ nhận được một cái gì đó không thành ngữ theo http://golang.org/doc/effective_go.html#Getters

Trả lời

64

Có một lý do kỹ thuật. Thư viện json không có quyền xem các trường bằng cách sử dụng phản ánh trừ khi chúng được xuất. Một gói chỉ có thể xem các trường không được xuất hiện của các loại trong gói riêng của nó

Để giải quyết vấn đề của bạn, những gì bạn có thể làm là tạo một loại không được xuất bản với các trường đã xuất. Json sẽ unmarshal vào một loại unexported nếu thông qua cho nó mà không có một vấn đề nhưng nó sẽ không hiển thị trong các tài liệu API. Sau đó, bạn có thể tạo loại được xuất để nhúng loại không được xuất. Loại được xuất này sau đó sẽ cần các phương pháp để triển khai các giao diện json.Marshalerjson.Unmarshaler.

Lưu ý: tất cả mã chưa được kiểm tra và thậm chí không thể biên dịch được.

type jsonData struct { 
    Field1 string 
    Field2 string 
} 

type JsonData struct { 
    jsonData 
} 

// Implement json.Unmarshaller 
func (d *JsonData) UnmarshalJSON(b []byte) error { 
    return json.Unmarshal(b, &d.jsonData) 
} 

// Getter 
func (d *JsonData) Field1() string { 
    return d.jsonData.Field1 
} 
+0

Để ghi lại, tôi phải Unmarshall sử dụng "json.Unmarshal (b, & d.jsonData)". Tôi đã làm điều gì đó sai, hay là điều đó được mong đợi? – Derek

+0

@Derek, cảm ơn, tôi đã cập nhật câu trả lời của mình. Như tôi đã nói mã chưa được kiểm tra. Tôi cũng dường như cũng quên một câu lệnh return trong phương thức 'UnmarshalJSON()' của tôi. Tôi cũng cố định cái này. –

+3

Tôi trễ một chút để hiển thị, nhưng ... trong khi các tác phẩm trên, Field1 và Field2 _are_ được xuất. Bạn có thể đọc và viết Field1 và Field2 của JsonData (với một chữ J) bên ngoài gói đó. Vì vậy, trong khi điều này là mát mẻ về lý thuyết, nó không thực sự làm bất cứ điều gì khác hơn là xuất khẩu cả loại và các lĩnh vực. – davidjosepha

41

Câu trả lời của Stephen hoàn tất. Là một sang một bên, nếu tất cả các bạn thực sự muốn là phím chữ thường trong json, bạn có thể tự xác định tên chủ chốt như sau:

type Whatever struct { 
    SomeField int `json:"some_field"` 
} 

Bằng cách đó, marshaling một Dù tạo ra chìa khóa "some_field" cho someField lĩnh vực (thay vì có "SomeField" trong json của bạn).

Nếu bạn đã chết trong việc giữ trường chưa được công bố, bạn cũng có thể triển khai giao diện json.Marshaler bằng cách xác định phương thức có chữ ký MarshalJSON() ([]byte, error). Một cách để làm điều này là sử dụng một cấu trúc theo nghĩa đen mà chỉ đơn giản đã xuất khẩu các phiên bản của các lĩnh vực unexported, như thế này:

type Whatever struct { 
    someField int 
} 

func (w Whatever) MarshalJSON() ([]byte, error) { 
    return json.Marshal(struct{ 
     SomeField int `json:"some_field"` 
    }{ 
     SomeField: w.someField, 
    }) 
} 

Đó có thể là một chút rườm rà, vì vậy bạn cũng có thể sử dụng một map[string]interface{} nếu bạn thích:

func (w Whatever) MarshalJSON() ([]byte, error) { 
    return json.Marshal(map[string]interface{}{ 
     "some_field": w.SomeField, 
    }) 
} 

Tuy nhiên cần lưu ý rằng marshaling interface{} có một số hãy cẩn thận và có thể làm những việc như soái uint64 đến một float, gây thiệt hại chính xác. (tất cả các mã chưa được kiểm tra)

+0

Về mặt kỹ thuật, TẤT CẢ các số trong Javascript là phao. –

+16

JSON không phải là JavaScript. Thông số JSON chỉ cho biết các ký tự nào có thể chấp nhận được, không phải các dải số nào hợp lệ. Một số như 876234958273645982736459827346598237465923847561203947812435968234659827346 vẫn hợp lệ trong JSON, ngay cả khi JavaScript không thể hiểu được. Đối với một ví dụ thế giới thực, API Twitter đại diện cho các ID tweet là số nguyên không dấu 64 bit, không hợp lệ trong JavaScript, nhưng là JSON hợp lệ. – jorelli

+1

Hiện tại, tất cả đều đúng, nhưng vẫn là tên là JSON, vốn có tên là "JavaScript Object Notation". Một trong những bit đáng ngạc nhiên nhỏ khiến bạn muốn đổi tên nó thành NJSON (NewJSON hoặc đúng hơn là NotJavaScript) :) – quetzalcoatl

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