代码之家  ›  专栏  ›  技术社区  ›  Roman Puchkovskiy

Jackson在编译为本机映像的Micronaut应用程序中找不到POJO的属性

  •  0
  • Roman Puchkovskiy  · 技术社区  · 4 年前

    https://micronaut.io/launch/ ,然后我添加了以下内容:

    @Controller
    public class HelloController {
        @Get("/hello")
        public Result hello() {
            return new Result("Hello world!");
        }
    }
    
    public class Result {
        private final String message;
    
        public Result(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    }
    

    然后我使用 ./mvnw clean package

    java -jar target/micronaut-minimal-1.0.jar ,它成功启动。它的反应正确:

    $ curl http://localhost:8080/hello
    {"message":"Hello world!"}
    

    现在,我构建一个本机映像:

    native-image -jar target/micronaut-minimal-0.1.jar target/app
    

    然后我运行它:

    target/app
    

    一开始还可以。

    现在,相同的请求会产生一个错误:

    $ curl http://localhost:8080/hello
    {"message":"Internal Server Error: Error encoding object [com.example.Result@7f21a9858b70] to JSON: No serializer found for class com.example.Result and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)"}
    

    我试着加上 @JsonProperty message getMessage() 方法(带或不带) value 属性),但没有用。

    我正在使用GraalVM CE 20.1.0(构建11.0.7+10-jvmci-20.1-b02)来运行和构建jar和映像。

    0 回复  |  直到 4 年前
        1
  •  1
  •   Roman Puchkovskiy    4 年前

    我找到了两种方法来解决这个问题:一种是具体的、更干净的,另一种是更普遍但更脏的。

    @内省注释

    更简洁的方法非常简单:只需使用 @Introspected :

    @Introspected
    public class Result {
        private final String message;
    
        public Result(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    }
    

    您可以使用Jackson.bean-introspection-module设置启用bean-introspection与Jackson的集成,以实现无反射JSON序列化和反序列化。

    但就我而言,它只是起了作用。

    反射结构

    如@Turing85所述,如 Result#message Result#getMessage() 未在代码中引用, native-image

    我们可以指导 本地映像 reflect-config.json ):

    [
      {
        "name" : "com.example.Result",
        "fields" : [
          { "name" : "message" }
        ],
        "methods" : [
          { "name" : "getMessage", "parameterTypes" : [] }
        ]
      }
    ]
    

    在这里,我们指示工具保持字段 message 方法 getMessage() .

    然后我们使用 -H:ReflectionConfigurationFiles :

    native-image --no-server -H:ReflectionConfigurationFiles=reflect-config.json -jar target/micronaut-minimal-0.1.jar target/app
    

    更多信息: https://github.com/oracle/graal/blob/master/substratevm/REFLECTION.md

    方法比较

    第二种方法更具普遍性,因为第一种方法只有在特别处理的情况下才有可能。如果一个工具仍然需要反射,你别无选择,只能坚持使用它。

        2
  •  0
  •   Shïvà Tömàr    3 年前

    @JsonSerialize
    public class Result {
        private final String message;
    
        public Result(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    }