You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus中Vertx JsonObject.mapTo映射嵌套JsonObject为空的问题求助

Vertx JsonObject.mapTo 嵌套JsonObject映射为空问题解决

问题描述

在Quarkus框架中使用Vertx的JsonObject.mapTo方法将JSON对象映射为自定义TelemetryDto实体类时,发现嵌套的options字段(类型为JsonObject)被映射为空对象{},而非预期的嵌套JSON内容。

相关代码

TelemetryDto实体类

package com.abc.telemetry.dto;

import io.vertx.core.json.JsonObject;

public class TelemetryDto {
    private String clientId;
    private String commandId;
    private String deviceRef;
    private String telemetryAttributeRef;

    private JsonObject options;

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getCommandId() {
        return commandId;
    }

    public void setCommandId(String commandId) {
        this.commandId = commandId;
    }

    public String getDeviceRef() {
        return deviceRef;
    }

    public void setDeviceRef(String deviceRef) {
        this.deviceRef = deviceRef;
    }

    public String getTelemetryAttributeRef() {
        return telemetryAttributeRef;
    }

    public void setTelemetryAttributeRef(String telemetryAttributeRef) {
        this.telemetryAttributeRef = telemetryAttributeRef;
    }

    public JsonObject getOptions() {
        return options;
    }

    public void setOptions(JsonObject options) {
        this.options = options;
    }

    public TelemetryDto() {
    }

    public TelemetryDto(String clientId, String commandId, String deviceRef, String telemetryAttributeRef,
            JsonObject options) {
        this.clientId = clientId;
        this.commandId = commandId;
        this.deviceRef = deviceRef;
        this.telemetryAttributeRef = telemetryAttributeRef;
        this.options = options;
    }

    @Override
    public String toString() {
        return "TelemetryDto{" +
                "clientId='" + clientId + '\'' +
                ", commandId='" + commandId + '\'' +
                ", deviceRef='" + deviceRef + '\'' +
                ", telemetryAttributeRef='" + telemetryAttributeRef + '\'' +
                ", options=" + options +
                '}';
    }
}

业务处理代码

package com.abc.telemetry.service;

import com.abc.telemetry.dto.TelemetryDto;
import io.quarkus.logging.Log;
import io.quarkus.vertx.ConsumeEvent;
import io.vertx.core.json.DecodeException;
import io.vertx.core.json.JsonObject;
import org.apache.commons.lang3.Validate;

import javax.enterprise.context.ApplicationScoped;
import javax.validation.ConstraintViolationException;

@ApplicationScoped
public class WidgetControlActionProcessor {

    /*
     * this is the lister to the Widget control action events
     * after reserving action, this method responsible handle further processing
     */
    @ConsumeEvent("widget-control-action-feed")
    public void widgetControlActionConsumer(String message) {
        Log.info("widget-control-action-feed: Reserved widget control action: " + message);
        Log.debug("Reserved action: " + message);

        try {
            JsonObject jsonMessage = new JsonObject(message);

            // Get telemetryDto and send to process
            Log.info("json object: " + jsonMessage);
            processWidgetControlAction(jsonMessage.mapTo(TelemetryDto.class));

        } catch (DecodeException e) {
            Log.error("Can't process action: " + e.getMessage());
            Log.debug(e);
        } catch (ConstraintViolationException e) {
            Log.error("Invalid message type: " + e.getMessage());
        }
    }

    private void processWidgetControlAction(TelemetryDto telemetryDto) {
       
    Log.info("telemetry object: "  + telemetryDto);


    }

    @Scheduled(every = "10s")
    public void we() {
    publishTelemetryToDashboard("widget-control-action-feed", "{\n" +
            "    \"clientId\": \"fgfgf1\",\n" +
            "    \"commandId\": 1,\n" +
            "    \"deviceRef\": \"emulator\",\n" +
            "    \"telemetryAttributeRef\":\"abc\",\n" +
            "    \"options\": {\n" +
            "        \"username\": \"nimrekha\",\n" +
            "        \"state\": \"0\"\n" +
            "    }\n" +
            "}");
}

}

日志信息

2023-03-09 17:57:25,023 INFO  traceId=c02b65fa0aba9f68ee6ea84481d92689, parentId=d9dff4c54d0af324, spanId=5d326389ab863d8f, sampled=true [co.abc.tel.ser.WidgetControlActionProcessor] [widgetControlActionConsumer] (vert.x-eventloop-thread-3) widget-control-action-feed: Reserved widget control action: {
    "clientId": "fgfgf1",
    "commandId": 1,
    "deviceRef": "emulator",
    "telemetryAttributeRef":"abc",
    "options": {
        "username": "nimrekha",
        "state": "0"
    }
}
2023-03-09 17:57:25,033 INFO  traceId=c02b65fa0aba9f68ee6ea84481d92689, parentId=d9dff4c54d0af324, spanId=5d326389ab863d8f, sampled=true [co.abc.tel.ser.WidgetControlActionProcessor] [widgetControlActionConsumer] (vert.x-eventloop-thread-3) json object: {"clientId":"fgfgf1","commandId":1,"deviceRef":"emulator","telemetryAttributeRef":"abc","options":{"username":"nimrekha","state":"0"}}
2023-03-09 17:57:25,053 INFO  traceId=c02b65fa0aba9f68ee6ea84481d92689, parentId=d9dff4c54d0af324, spanId=5d326389ab863d8f, sampled=true [co.abc.tel.ser.WidgetControlActionProcessor] [processWidgetControlAction] (vert.x-eventloop-thread-3) telemetry object: TelemetryDto{clientId='fgfgf1', commandId='1', deviceRef='emulator', telemetryAttributeRef='abc', options={}}

解决方案

方法一:手动提取嵌套JsonObject

直接绕过mapTo对嵌套字段的自动映射,手动从原JsonObject中提取options并设置到Dto对象:

JsonObject jsonMessage = new JsonObject(message);
TelemetryDto telemetryDto = jsonMessage.mapTo(TelemetryDto.class);
// 手动设置options字段
telemetryDto.setOptions(jsonMessage.getJsonObject("options"));
processWidgetControlAction(telemetryDto);

这种方式简单直接,不需要修改实体类或依赖,适合快速解决问题。

方法二:添加Jackson注解增强自动映射

Vertx的mapTo在Quarkus环境中默认依赖Jackson处理序列化,给options字段添加@JsonProperty注解明确映射关系:

package com.abc.telemetry.dto;

import io.vertx.core.json.JsonObject;
import com.fasterxml.jackson.annotation.JsonProperty;

public class TelemetryDto {
    // ... 其他字段不变
    @JsonProperty("options")
    private JsonObject options;
    // ... 其他方法不变
}

确保项目中已包含Quarkus的Jackson扩展(默认已集成,若缺失可添加pom依赖):

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>

方法三:使用Jackson ObjectMapper直接转换

完全绕过Vertx的mapTo,使用Jackson的ObjectMapper直接解析JSON字符串到Dto,这种方式对嵌套对象的支持更完善:

import com.fasterxml.jackson.databind.ObjectMapper;
// ...
try {
    ObjectMapper mapper = new ObjectMapper();
    TelemetryDto telemetryDto = mapper.readValue(message, TelemetryDto.class);
    processWidgetControlAction(telemetryDto);
} catch (IOException e) {
    Log.error("JSON解析失败: " + e.getMessage());
}

若需要支持Vertx的JsonObject类型,需添加vertx-jackson-databind依赖:

<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-jackson-databind</artifactId>
</dependency>

内容的提问来源于stack exchange,提问作者Kavishka Madhushan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:24:55