簡體   English   中英

將對象和對象列表映射到 Json

[英]Map with object and list of objects to Json

我有兩個主要的模型類: CustomerProduct

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"}
        ]
    }
]

提示:分離域對象( CustomerProduct )和數據傳輸的表示對象( CustomerDtoProductDto )通常也是一個好主意,因為它允許為任何具體的表示實現創建表示(一個用於各種 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM