Объект POST запроса Spring Boot содержит почти все нулевые поля с классом Avro

#java #spring #spring-boot #avro

#java #spring #spring-boot #avro

Вопрос:

У нас есть следующий простой веб-сервер:

 package spring;

import avro.BatteryEvent;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.Date;

@RestController
public class EnergyResourcesController {
    private final Date date = new Date();

    @PostMapping("/event/{uuid}")
    BatteryEvent postBatteryEvent(
        @PathVariable("uuid") String uuid,
        @RequestBody BatteryEvent batteryEvent) throws IOException {
        batteryEvent.setTime(date.getTime());
        return batteryEvent;
    }
}
 

Он использует a BatteryEvent , который является сгенерированным Avro классом, который построен на основе следующей схемы Avro:

 {
  "namespace": "avro",
  "type": "record",
  "name": "BatteryEvent",
  "fields": [
    {
      "name": "charging_source",
      "type": [
        "string",
        "null"
      ]
    },
    {
      "name": "processor4_temp",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "device_id",
      "type": [
        "string",
        "null"
      ]
    },
    {
      "name": "processor2_temp",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "processor1_temp",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "charging",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "current_capacity",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "inverter_state",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "moduleL_temp",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "moduleR_temp",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "processor3_temp",
      "type": [
        "int",
        "null"
      ]
    },
    {
      "name": "soC_regulator",
      "type": [
        "float",
        "null"
      ]
    },
    {
      "name": "time",
      "type": [
        "long",
        "null"
      ],
      "logicalType": "local-timestamp-millis"
    }
  ]
}
 

Мы отправляем веб-серверу следующий JSON,

 {
  "charging_source": "utility",
  "processor4_temp": 160,
  "device_id": "18806072-81ca-48ed-b01a-b080f2d8a1fa",
  "processor2_temp": 96,
  "processor1_temp": 60,
  "charging": -912,
  "current_capacity": 10948,
  "inverter_state": 1,
  "moduleL_temp": 199,
  "moduleR_temp": 91,
  "processor3_temp": 152,
  "soC_regulator": 26.598085
}
 

Проблема BatteryEvent в том, что мы получаем все null значения, кроме charging поля, например:

 {"charging_source": null, "processor4_temp": null, "device_id": null, "processor2_temp": null, "processor1_temp": null, "charging": -261, "current_capacity": null, "inverter_state": null, "moduleL_temp": null, "moduleR_temp": null, "processor3_temp": null, "soC_regulator": null, "time": null}
 

Мой вопрос в том, почему это так? Все отправленные данные являются допустимыми JSON, и наш класс Avro также является допустимым. Наш сервер Spring Boot — это простой и корректный код, который был взят из собственной документации Spring Boot. Я хочу, чтобы данные, которые Spring Boot передает BatteryEvent объекту, содержали значения из отправленного JSON события батареи.

Ответ №1:

Я не уверен, в чем основная причина вашей проблемы, но, похоже, есть некоторые проблемы с сериализацией / десериализацией JSON.

Когда я попытался воспроизвести вашу проблему, согласно вашей информации, я получал некоторое исключение, которое я разрешил, используя решение, упомянутое здесь здесь

После этого, когда я запускаю POST API, я получил ожидаемый результат со всеми заполненными значениями.

Вы можете проверить мой код здесь здесь

Не могли бы вы предоставить дополнительную информацию о своем коде, например, изменили ли вы процесс сериализации / десериализации по умолчанию? Это поможет получить больше представления о том, почему в вашем коде свойства устанавливаются как null

Ниже приведены запрос и ответ из моего примера

Запрос

 {
    "charging_source": "utility",
    "processor4_temp": 160,
    "device_id": "18806072-81ca-48ed-b01a-b080f2d8a1fa",
    "processor2_temp": 96,
    "processor1_temp": 60,
    "charging": -912,
    "current_capacity": 10948,
    "inverter_state": 1,
    "moduleL_temp": 199,
    "moduleR_temp": 91,
    "processor3_temp": 152,
    "soC_regulator": 26.598085
}
 

Ответ

 {
    "charging_source": "utility",
    "processor4_temp": 160,
    "device_id": "18806072-81ca-48ed-b01a-b080f2d8a1fa",
    "processor2_temp": 96,
    "processor1_temp": 60,
    "charging": -912,
    "current_capacity": 10948,
    "inverter_state": 1,
    "moduleL_temp": 199,
    "moduleR_temp": 91,
    "processor3_temp": 152,
    "soC_regulator": 26.598085,
    "time": 1609404352570,
    "moduleRTemp": 91,
    "moduleLTemp": 199,
    "inverterState": 1,
    "soCRegulator": 26.598085,
    "deviceId": "18806072-81ca-48ed-b01a-b080f2d8a1fa",
    "processor1Temp": 60,
    "currentCapacity": 10948,
    "processor3Temp": 152,
    "processor4Temp": 160,
    "chargingSource": "utility",
    "processor2Temp": 96
}
 

Комментарии:

1. Спасибо за вашу помощь! Когда мы переместили каталог сгенерированных источников Avro из src/main/resources/avro в ${project.build.directory}/generated-sources , мы смогли исправить проблемы с сериализацией / десериализацией. Мы бы не смогли этого сделать без вашего pom файла примера в созданном вами репозитории. Большое спасибо за вашу помощь!

Ответ №2:

Имя поля в entity должно совпадать с именем ключа в json

Комментарии:

1. Все имена полей в схеме Avro точно соответствуют именам ключей в полученном JSON.