[英]Map with object and list of objects to Json
我有兩個主要的模型類: Customer
和Product
public class Customer {
String name;
String surname;
int age;
BigDecimal cash;
}
public class Product {
String name;
Category category;
BigDecimal price;
}
我想建立json
與文件Map<Customer, List<Product>>
當我寫json
用我的方法的文件數據,正確的工作-我相信這一點-在json
文件顯示這句法
{
"Customer{name\u003d\u0027Custo1\u0027, surname\u003d\u0027Surname\u0027, age\u003d18, cash\u003d1200}": [
{
"name": "prod1",
"category": "CLOTHES",
"price": 12000
},
{
"name": "prod2",
"category": "ELECTRONIC",
"price": 15000
}
]
}
然后當我想讀取這個文件時, Exception in thread "main" java.util.NoSuchElementException: No value present
的錯誤Exception in thread "main" java.util.NoSuchElementException: No value present
出現所以我認為來自 json 文件的Customer
語法無法識別。 所以我嘗試使用下面的語法自行將數據寫入json
文件,但它不起作用
[
{
"name": "Abc",
"surname": "Def",
"age": 14,
"cash": "2000"
}
:
[
{
"name": "prod1",
"category": "CLOTHES",
"price": 12000
},
{
"name": "prod2",
"category": "ELECTRONIC",
"price": 15000
}
]
]
json轉換器方法:
public void toJson(final T item) {
try (FileWriter fileWriter = new FileWriter(jsonFilename)) {
fileWriter.write(gson.toJson(item));
} catch (Exception e) {
throw new ValidatorException(e.getMessage());
}
}
@Tom在您遇到的問題上是正確的。 我將解釋原因並提出另一種解決方案。
您的第一個 JSON 在技術上是有效的 JSON,但不能反序列化,因為映射鍵是 Gson 默認使用的Customer.toString()
方法的結果。 這就是為什么它看起來很奇怪,就像一個調試字符串,並且不能反序列化:幾乎總是無法從toString()
結果中恢復對象( toString
主要用於調試/記錄目的,提供基本的有關特定對象狀態的信息,根本不需要公開其所有內部結構)。
您的第二個 JSON 是無效的JSON。 時期。
Tom 將產品列表作為客戶類別的一部分的建議是完全正確的。 像這樣實現它可以讓您將所有內容序列化為這樣的列表:
[
{
"name": "john",
"products": [
{"name": "prod1"},
{"name": "prod2"}
]
}
]
提示:分離域對象( Customer
和Product
)和數據傳輸的表示對象( CustomerDto
和ProductDto
)通常也是一個好主意,因為它允許為任何具體的表示實現創建表示(一個用於各種 JSON 實現庫,兩個用於其他 -面向格式的工具,第三個用於持久性,四個用於 UI 視圖等),因此它可能被實現,例如將Map<Customer, List<Product>>
為List<CustomerDto>
並返回(可能通過使用 MapStruct 等映射器生成器) .
如果由於某種原因無法重新組織您的域類或創建 Gson 友好的 DTO 映射,或者您可以保持它盡可能簡單並且您沒有那個微不足道的 JSON 結構(只要您了解此解決方案中格式的含義:進化、分布等),然后您可以啟用特殊的 Gson 模式來支持這種地圖。 它生成可以序列化和反序列化的有效 JSON,但它的實現方式在我看來有點反模式,因為使用數組作為數據容器會丟失語義。
@AllArgsConstructor
@EqualsAndHashCode
@ToString
final class Customer {
final String name;
}
@AllArgsConstructor
@EqualsAndHashCode
@ToString
final class Product {
final String name;
}
public final class MapTest {
private static final Gson gson = new GsonBuilder()
.enableComplexMapKeySerialization()
.create();
private static final TypeToken<Map<Customer, List<Product>>> customerToProducts = new TypeToken<Map<Customer, List<Product>>>() {};
@Test
public void test() {
final Map<Customer, List<Product>> ordersBefore = ImmutableMap.of(
new Customer("john"), ImmutableList.of(new Product("prod1"), new Product("prod2"))
);
final String json = gson.toJson(ordersBefore, customerToProducts.getType());
Assertions.assertEquals("[[{\"name\":\"john\"},[{\"name\":\"prod1\"},{\"name\":\"prod2\"}]]]", json);
final Map<Customer, List<Product>> ordersAfter = gson.fromJson(json, customerToProducts.getType());
Assertions.assertEquals(ordersBefore, ordersAfter);
}
}
請注意,它會像這樣生成 JSON(索引0
表示鍵,索引1
表示值):
[
[
{"name": "john"},
[
{"name": "prod1"},
{"name": "prod2"}
]
]
]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.