Micronaut序列化实现方法及替代Grails的JSON.registerObjectMarshaller方案
2. 从Grails的
JSON.registerObjectMarshaller迁移到Micronaut的方案 Grails里的JSON.registerObjectMarshaller用来自定义对象的JSON输出,Micronaut没有直接对应的API,但可以用Jackson的序列化机制完美替代,下面是几种常用方案:
全局自定义序列化器(对应全局marshaller)
原来Grails的全局marshaller代码大概是这样:JSON.registerObjectMarshaller(User) { User user -> return [ username: user.name.toLowerCase(), age: user.age, is_adult: user.age >= 18 ] }在Micronaut里,我们可以写自定义序列化器并全局注册:
- 编写序列化器:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.IOException; public class GlobalUserSerializer extends StdSerializer<User> { public GlobalUserSerializer() { super(User.class); } @Override public void serialize(User user, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeStartObject(); gen.writeStringField("username", user.getName().toLowerCase()); gen.writeNumberField("age", user.getAge()); gen.writeBooleanField("is_adult", user.getAge() >= 18); gen.writeEndObject(); } } - 全局注册:创建Jackson配置工厂类,将序列化器加入Jackson模块:
这样所有返回User对象的接口都会用这个序列化逻辑,和Grails全局marshaller效果一致。import com.fasterxml.jackson.databind.module.SimpleModule; import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.Factory; import io.micronaut.jackson.JacksonConfiguration; @Factory public class CustomJacksonConfig { @Bean public JacksonConfiguration jacksonConfig() { JacksonConfiguration config = new JacksonConfiguration(); SimpleModule customModule = new SimpleModule(); customModule.addSerializer(User.class, new GlobalUserSerializer()); config.getModules().add(customModule); return config; } }
- 编写序列化器:
局部自定义序列化(对应局部marshaller)
如果只需要某个类或接口用特定序列化逻辑,直接在实体类上标注@JsonSerialize(using = XXXSerializer.class)即可:@Introspected @JsonSerialize(using = UserSerializer.class) public class User { // 字段和方法 }这样只有该类的实例会使用指定序列化器,其他地方不受影响。
用
@JsonView实现多视图序列化
如果原来用marshaller是为了不同API返回不同字段集合,Micronaut支持Jackson的@JsonView注解,非常适合这种场景:- 定义视图接口:
public class UserViews { public interface Basic {} // 基础视图,返回核心字段 public interface Detailed extends Basic {} // 详细视图,继承基础字段并返回更多内容 } - 在实体类字段上标注对应视图:
@Introspected public class User { @JsonView(UserViews.Basic.class) private String name; @JsonView(UserViews.Basic.class) private int age; @JsonView(UserViews.Detailed.class) private String email; @JsonView(UserViews.Detailed.class) private LocalDate joinDate; } - 在控制器方法上指定视图:
访问@Controller("/users") public class UserController { @Get("/basic") @JsonView(UserViews.Basic.class) public User getBasicUser() { return new User("Charlie", 25, "charlie@example.com", LocalDate.now()); } @Get("/detailed") @JsonView(UserViews.Detailed.class) public User getDetailedUser() { return new User("Charlie", 25, "charlie@example.com", LocalDate.now()); } }/users/basic只会返回name和age,/users/detailed会返回所有字段,完美替代Grails中不同marshaller对应不同场景的需求。
- 定义视图接口:
内容的提问来源于stack exchange,提问作者iUbaid
相关产品推荐
相关产品推荐

