当前位置: 首页 > 知识库问答 >
问题:

gson将字段反序列化为null

严俊友
2023-03-14

首先,我想说这是一个大学项目。

我有三节课<代码>订单抽象类和从订单继承的交付DineIn类。

我使用Gson序列化/反序列化子类,但我遇到了一点问题。订单类有一个字段orderType,gson使用该字段来确定订单类型,DineIn或Delivery。

序列化工作得很好。问题是,每当我尝试反序列化时,类型字段值都不会读取,并且总是设置为null,即使它存在于JSON文件中。当有很多字段时,就会发生这种情况,因为当我尝试在较小的规模上测试这个程序时,订单类只有2个字段(orderType和orderNo),一切都很好。我不知道我做错了什么。我尝试在这个网站上搜索,几乎总是遇到建议,使自定义类型适配器和序列化器,但我们没有在大学里研究过它们,我不想使用它们(讲师扣分使用任何他没有教过的东西,我几乎失败了上次我从他那里学了一门课,因为我用了他没有教过的东西。不过,他似乎对第三方库没有问题)。

守则:

public class Main {
    public static final List<Order> ordersList = read();
    public static void main(String[] args) {
        System.out.println(ordersList.get(0).getOrderType());
        System.out.println(ordersList.get(0) instanceof DineIn ? "DineIn": "Delivery");
    }

    private static List<Order> read(){
        List<Order> ordersList = new ArrayList<>();
        Type type = new TypeToken<ArrayList<Order>>() {
        }.getType();


        RuntimeTypeAdapterFactory<Order> adapter = RuntimeTypeAdapterFactory.of(Order.class, "orderType")
                .registerSubtype(DineIn.class)
                .registerSubtype(Delivery.class);

        Gson gson = new GsonBuilder().registerTypeAdapterFactory(adapter).create();
        JsonReader ordersJsonReader;
        try {
            ordersJsonReader = new JsonReader(new FileReader("orders.json"));
            List<Order> tempOrdersList = gson.fromJson(ordersJsonReader, type);
            if (tempOrdersList != null) ordersList = tempOrdersList;
            ordersJsonReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ordersList;
    }
}

abstract class Order {
    private final int orderNumber;
    private final String date, customerName;
    private final int discountRate;
    private final String paymentMethod;
    private String orderStatus;
    private int grossTotal = 0;
    private double netTotal = 0;
    private int totalItems = 0;
    protected final String orderType;

    public abstract String getOrderType();
    public abstract double getExtraCharges();

    public Order(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems, String orderType) {
        this.orderNumber = orderNumber;
        this.date = date;
        this.customerName = customerName;
        this.discountRate = discountRate;
        this.paymentMethod = paymentMethod;
        this.orderStatus = orderStatus;
        this.grossTotal = grossTotal;
        this.netTotal = netTotal;
        this.totalItems = totalItems;
        this.orderType = orderType;
    }
}

class DineIn extends Order {
    private double serviceCharges = 150;

    public DineIn(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems) {
        super(orderNumber, date, customerName, discountRate, paymentMethod, orderStatus, grossTotal, netTotal, totalItems, "DineIn");
    }

    @Override
    public String getOrderType() {
        return orderType;
    }

    @Override
    public double getExtraCharges() {
        return serviceCharges;
    }
}

class Delivery extends Order {
    private double deliveryCharges = 100;

    public Delivery(int orderNumber, String date, String customerName, int discountRate, String paymentMethod, String orderStatus, int grossTotal, double netTotal, int totalItems) {
        super(orderNumber, date, customerName, discountRate, paymentMethod, orderStatus, grossTotal, netTotal, totalItems, "Delivery");
    }

    @Override
    public String getOrderType() {
        return orderType;
    }

    @Override
    public double getExtraCharges() {
        return deliveryCharges;
    }
}

JSON:

[
  {
    "serviceCharges": 150.0,
    "orderNumber": 1,
    "date": "12/12/2021",
    "customerName": "Ali",
    "discountRate": 15,
    "paymentMethod": "Card",
    "orderStatus": "Preparing",
    "grossTotal": 5000,
    "netTotal": 4500.0,
    "totalItems": 14,
    "orderType": "DineIn"
  }
]

共有1个答案

陈开宇
2023-03-14

在代码中,您有一个层次结构,DineInDeliveryOrder扩展而来。设置orderType字段的方式是通过super()构造函数中的显式字符串参数。

但是,Gson不使用构造函数来实例化对象。它使用一个特殊的无参数构造函数,并通过反射填充值:https://stackoverflow.com/a/40442037/9698467

在这种情况下,问题来自RuntimeTypeAdapterFactory,它从它读取的JSON中删除了orderType字段。这里的源代码证实:https://github.com/google/gson/blob/86d88c32cf6a6b7a6e0bbc855d76e4ccf6f120bb/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java#L202

正如@Fluffy建议的,库的新版本包括维护标志,这应该允许保留字段:https://github.com/google/gson/blob/c1e7e2d2808b042cbe47ca31869ee6ccc62c5417/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java#L214

 类似资料:
  • 我正在使用gson进行改造,将json反序列化为领域对象。这在大多数情况下都很有效。处理问题时会出现麻烦 RealmList(字符串(或任何其他基本数据类型)) 由于Realm不支持RealmList,其中E不扩展Realm对象,所以我将字符串包装在RealmObject中。 我的领域对象如下 SimpleRealmObj工作正常,因为它只有字符串元素 如何反序列化stringStuff?我试过使

  • 我正在努力用本地化反序列化世界天气在线API结果。 是否有更好、更简单的解决方案,只为lang对象编写一个自定义反序列化器,并允许GSON自动反序列化其余数据?

  • 是否有方法序列化类的瞬态字段?文档中提到默认情况下不支持它,但是否有办法打开它? 非常感谢

  • 我想序列化特定字段或类的空值。 在GSON中,选项适用于整个JSON。 例子: 使用GSON创建JSON: 电流输出: 期望输出: 如何达到预期的输出? 首选解决方案应具有以下特性: 默认情况下不要序列化空值 为具有特定注释的字段序列化空值。

  • 我有一个Android应用程序,与Spring开发的RESTAPI联系。应用程序很好地序列化了一个对象,但是Spring应用程序在每个字段不为null时将其解析为null。有什么不对劲?我该怎么办? 这是REST API方法签名:cambioPassword(@quiestHeader(授权)字符串头,PasswordChange userData) 注意:应用程序和API都使用Gson(我没有在

  • 有没有办法用Jackson来配置这个?如果没有,是否有一种有效的方法来编写(假设中的值可以是更复杂但众所周知的一致类型)?