Administrator
2026-09-21 e9871a602f4a69a3674b2cb5e7678edd0d338ea5
fix(gateApi): 解决枚举定义不完整导致的反序列化异常

- 修复了 FuturesOrder.FinishAsEnum 枚举缺少 price_rate_protected 等值的问题
- 添加了对 posMarginMode 字段的特殊处理,避免 cross|dual 组合值的反序列化错误
- 优化了 Gson 排除策略,精确跳过特定类的字段解析
- 更新了注释文档,详细说明了枚举同步延迟问题及解决方案
1 files modified
26 ■■■■■ changed files
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -188,13 +188,19 @@
    }
    /**
     * 构建容错的 JSON 序列化器,跳过 {@code finishAs} 字段的反序列化。
     * 构建容错的 JSON 序列化器,跳过部分枚举不完整字段的反序列化。
     *
     * <p>gate-api SDK 的 {@code FuturesOrder.FinishAsEnum} 枚举不完整,缺少
     * {@code price_rate_proteced}(价格保护)等 Gate 实际会返回的值。反序列化未知
     * 枚举值时 {@code fromValue} 会抛 {@link IllegalArgumentException},导致已成功
     * 提交的订单被误判为失败(如日志 {@code Unexpected value 'price_rate_proteced'})。
     * 业务不使用 finishAs 字段,因此通过 Gson 排除策略直接跳过其解析。
     * <p>gate-api SDK 的枚举定义滞后于交易所实际返回值,反序列化未知枚举值时
     * {@code fromValue} 会抛 {@link IllegalArgumentException},导致接口被误判为失败。
     * 已确认业务不使用以下字段,因此通过 Gson 排除策略直接跳过其解析:
     * <ul>
     *   <li>{@code finishAs}:{@code FuturesOrder.FinishAsEnum} 缺少
     *       {@code price_rate_protected}(价格保护)等值(如日志
     *       {@code Unexpected value 'price_rate_proteced'});</li>
     *   <li>{@code posMarginMode}:{@code FuturesPriceTriggeredOrder.PosMarginModeEnum}
     *       只定义 {@code cross}/{@code dual},而 {@code cancelPriceTriggeredOrderList}
     *       会返回组合值 {@code cross|dual}(如日志 {@code Unexpected value 'cross|dual'})。</li>
     * </ul>
     */
    private static JSON buildLenientJson() {
        JSON json = new JSON();
@@ -202,7 +208,13 @@
                .setExclusionStrategies(new ExclusionStrategy() {
                    @Override
                    public boolean shouldSkipField(FieldAttributes f) {
                        return "finishAs".equals(f.getName());
                        if ("finishAs".equals(f.getName())) {
                            return true;
                        }
                        // 仅跳过 FuturesPriceTriggeredOrder 的 posMarginMode,避免误伤
                        // FuturesOrder / Position 的同名字段(二者语义为 isolated/cross)
                        return "posMarginMode".equals(f.getName())
                                && FuturesPriceTriggeredOrder.class.equals(f.getDeclaringClass());
                    }
                    @Override