【发布时间】:2017-10-29 23:44:31
【问题描述】:
我有一个简单而复杂的问题:是否可以在缺少 JSON 属性时调用 JsonDeserializer?
为什么:我有一个 RegisterableProfile,它对应于用户填充并发送到服务器的表单。在最简单的形式中,它看起来像这样:
JSON-Request,将映射到 RegisterableProfile:
{
"username": "someUser",
"password": "somePass",
"email": "some@mail.com",
"language": "en"
}
它映射到的实体(RegisterableProfile):
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@MappedSuperclass
public class RegisterableProfile extends CredentialsProfile {
@Column(nullable = false, unique = true)
private String email;
@OneToOne
@Convert(converter = LanguageConverter.class)
private Language language;
@Override
public String toString() {
return new StringBuilder(RegisterableProfile.class.getSimpleName())
.append(" {")
.append("name : '").append(getUsername()).append("',")
.append("password : '").append(getPassword()).append("',")
.append("email : '").append(email)
.append("'}")
.toString();
}
}
请注意,CredentialsProfile 仅提供用户名和密码并与此类分开,因为在初始登录时可能会单独发生。
语言实体:
@JsonDeserialize(using = LanguageDeserializer.class)
@Data
@NoArgsConstructor
@Entity(name = "Languages")
public class Language {
@Id
@Column(nullable = false, unique = true)
private String languageCode;
@Column(nullable = false, unique = true)
private String name;
@Column(nullable = false, unique = true)
private String i18nName;
private boolean localizeUi = false;
private boolean canChoose = false;
private boolean defaultLanguage = false;
}
使用 LanguageDeserializer 将 JSON 字符串中的“语言”属性正确转换为语言对象 - 如果该属性存在。 但是:如果 属性缺失或为空,则不会调用 LanguageDeserializer#deserialize 方法并且 RegisterableProfile 中的“语言”属性保持为空。
我可能可以通过检查我的 ProfileService 方法中的语言属性是否为“null”并将其设置在那里来解决这个问题,但它似乎不像在缺少的属性上调用自定义反序列化器那样干净.
另一个想法(仍然是一种解决方法)是为 RegisterableProfile 提供一个自定义反序列化器,并让它检测语言属性是否丢失或其他什么,但我不知道如何去做。
我的LanguageDeserializer:
public class LanguageDeserializer extends JsonDeserializer<Language> {
@Autowired
private LanguageService languageService;
@Override
public Language deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException, JsonProcessingException {
final JsonNode node = p.readValueAsTree();
final String languageCode = node.asText();
return languageService.getLanguage(languageCode);
}
}
注意:languageService.getLanguage(...) 始终返回与 languageCode 匹配的 Language-object 或默认 Language-object。
此外:解决方案应该使用 spring-boot(及其库堆栈)。我目前使用的是 spring-boot 版本 1.5.7.RELEASE 和 2.8.10(与 spring-boot 捆绑)。
【问题讨论】:
标签: java spring-boot jackson