Chuyển đổi tên thuộc tính kiểu JSON thành tên Java CamelCase với GSON


106

Tôi đang sử dụng GSON để chuyển đổi dữ liệu JSON mà tôi nhận được sang một đối tượng Java. Nó hoạt động khá tốt trong tất cả các thử nghiệm của tôi. Vấn đề là các đối tượng thực của chúng ta có một số thuộc tính được đặt tên như is_online. GSON chỉ ánh xạ chúng nếu chúng được đặt tên hoàn toàn bằng nhau, sẽ rất tuyệt nếu GSON chuyển đổi tên thành trường hợp lạc đà Java isOnline.

Có vẻ như điều này là khả thi khi tạo dữ liệu JSON, trường hợp lạc đà được chuyển đổi thành gạch dưới các từ được phân tách trong JSON. Nhưng tôi không thể tìm ra cách xác định điều này theo cách khác.


5
Tôi đề nghị chấp nhận một câu trả lời
JeanValjean

Câu trả lời:


313

Tôi nhận thấy cài đặt sau hoạt động hoàn hảo khi đọc json với các thuộc tính gạch dưới và sử dụng camelcasing trong các mô hình của tôi.

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .create()

2
Câu trả lời tuyệt vời, cảm ơn bạn! @janusz, nếu bất kỳ câu trả lời nào trong số này giúp ích cho bạn, vui lòng đánh dấu chúng là Câu trả lời được chấp nhận.
sufinawaz

1
Nếu bạn gặp trường hợp tên chứa hai dấu gạch dưới, nó sẽ bỏ qua dấu gạch dưới đầu tiên. Ví dụ. this_key_has__two_underscores sẽ được chuyển đổi thành thisKeyHas_TwoUnderscores và ngược lại. Điểm mấu chốt là FieldNamingPolicy nơi enum nói "chữ thường" với dấu gạch dưới trong khi ở đây tên được chuyển đổi có chữ hoa với dấu gạch dưới (_T).
Deepak GM

Rất đơn giản, giúp tôi không phải chú thích một loạt các trường!
William T. Mallard

98

Bạn có thể sử dụng SerializedNamechú thích:

@SerializedName("field_name_in_json")
private final String fieldNameInJava;

Lưu ý: Khi bạn đã đặt FieldNamingPolicyrồi, SerializedNamesẽ ghi đè cài đặt của nó cho trường cụ thể đó (khá tiện dụng cho các trường hợp đặc biệt).


2

Hãy nhớ rằng ví dụ của bạn là một trường hợp khó hiểu. Nếu bạn có thuộc tính 'foo' thì getter của nó phải được đặt tên là 'getFoo' và nếu bạn có thuộc tính có tên 'foo_bar' thì getter của nó phải được đặt tên là 'getFooBar', tuy nhiên, trong ví dụ của bạn, bạn đang ánh xạ boolean và boolean có quy ước đặt tên trường hợp đặc biệt trong java. Thuộc tính boolean nguyên thủy được đặt tên trực tuyến nên có getter có tên là 'isOnline', KHÔNG PHẢI 'getOnline' hoặc thậm chí tệ hơn, 'getIsOnline'. Một đối tượng trình bao bọc boolean (tức là Boolean) không nên tuân theo trường hợp đặc biệt này và thuộc tính có tên 'trực tuyến' phải có getter có tên 'getOnline'.

Do đó, có thuộc tính boolean với 'is' trong tên là một trường hợp khó hiểu, nơi bạn sẽ muốn loại bỏ tiền tố cụ thể này trong quá trình chuyển đổi của mình. Theo hướng ngược lại, mã của bạn có thể muốn kiểm tra đối tượng json cho cả tên thuộc tính thô cũng như phiên bản 'is_XXX'.


2

Tôi nghĩ những gì bạn muốn là ở đây . Sử dụng chú thích, bạn có thể cho GSON biết rằng mySuperCoolField thực sự được gọi là this_field_is_fun trong JSON và nó sẽ giải nén nó một cách chính xác. Ít nhất thì tôi nghĩ nó cũng hoạt động cho quá trình khử trên không.

Nếu điều đó không hiệu quả, bạn có thể sử dụng JsonSerializer / JsonDeserializers tùy chỉnh, hoạt động tốt, nhưng bạn phải cập nhật chúng để thay đổi trong lớp của mình (như khi bạn thêm trường). Bạn mất phép tự động.

Điều dễ dàng nhất để làm (sẽ xấu, nhưng rất sạch sẽ và đơn giản nếu gợi ý đầu tiên không hoạt động) là chỉ cần đặt tên trường theo cách khiến GSON hài lòng và thêm các phương thức truy cập bổ sung với tên bạn thích , ví dụ

public boolean isXXX() {return this.is_XXX;}

điều dễ dàng là những gì tôi đang làm vào lúc này và nó hoạt động tốt. Tất cả mã kiểu java xấu xí không điển hình đều được ẩn trong các lớp dữ liệu và không ai từ bên ngoài nhìn thấy nó. Nhưng nó vẫn làm tôi khó chịu một chút :)
Janusz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.