gpt4 book ai didi

java - "Relaxed"Jackson 的字段名称

转载 作者:太空宇宙 更新时间:2023-11-04 09:42:09 26 4
gpt4 key购买 nike

我正在研究 Jackson 配置,我想知道是否有任何选项可以反序列化不同类型的字段模式。

例如,我有一个对象:

class DeserializeIt {
String fieldOne;
String fieldOneAndHalf;
String fieldTwo;
String fieldThree;
String fieldFour;

//getters setters etc.
}

我有以下 JSON 有效负载:

{
"fieldOne" : "value1",
"field_ONE-and_Half": "value15",
"FIELD_TWO": "value2",
"FIELD_THREE" : "value3",
"field_four": "value4"
}

我想将所有这些字段名称反序列化为驼峰式大小写,无一异常(exception)。

我尝试创建自定义 PropertyNamingStrategy 但它从另一个方向进行:它不会将分隔字段转换为驼峰式大小写,而是尝试转换对象字段并在解析的字符串中搜索它们。

由于我无法传递可能的字符串列表而不是一个变体(fieldOne 可以变为 field-onefield_onefield-ONE 等),因此这不起作用。

你知道我还可以配置什么来实现如此轻松的反序列化吗?

最佳答案

我们需要扩展com.fasterxml.jackson.databind.deser.BeanDeserializerModifiercom.fasterxml.jackson.databind.deser.BeanDeserializer来反序列化POJO类。下面的解决方案取决于您使用的版本,因为我从基类复制了一些代码,该代码尚未准备好拦截额外的功能。如果您的 POJO 类没有任何额外的配置,vanillaDeserialize 方法将被调用,我们将尝试改进该方法。

在其他情况下,您需要调试此解串器并根据需要更新其他位置。以下解决方案使用版本 2.9.8 .

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.JsonTokenId;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
import com.fasterxml.jackson.databind.module.SimpleModule;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class JsonApp {

public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();

SimpleModule relaxedModule = new SimpleModule();
relaxedModule.setDeserializerModifier(new RelaxedBeanDeserializerModifier());

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(relaxedModule);

System.out.println(mapper.readValue(jsonFile, DeserializeIt.class));
}
}

class RelaxedBeanDeserializerModifier extends BeanDeserializerModifier {

@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
JsonDeserializer<?> base = super.modifyDeserializer(config, beanDesc, deserializer);
if (base instanceof BeanDeserializer) {
return new RelaxedBeanDeserializer((BeanDeserializer) base);
}

return base;
}
}

class RelaxedBeanDeserializer extends BeanDeserializer {

private Map<String, String> properties = new HashMap<>();

public RelaxedBeanDeserializer(BeanDeserializerBase src) {
super(src);
_beanProperties.forEach(property -> {
properties.put(property.getName().toLowerCase(), property.getName());
});
}

public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
// common case first
if (p.isExpectedStartObjectToken()) {
if (_vanillaProcessing) {
return vanillaDeserialize(p, ctxt, p.nextToken());
}
// 23-Sep-2015, tatu: This is wrong at some many levels, but for now... it is
// what it is, including "expected behavior".
p.nextToken();
if (_objectIdReader != null) {
return deserializeWithObjectId(p, ctxt);
}
return deserializeFromObject(p, ctxt);
}
return _deserializeOther(p, ctxt, p.getCurrentToken());
}

protected Object vanillaDeserialize(JsonParser p, DeserializationContext ctxt, JsonToken t) throws IOException {
final Object bean = _valueInstantiator.createUsingDefault(ctxt);
// [databind#631]: Assign current value, to be accessible by custom serializers
p.setCurrentValue(bean);

if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
String propName = p.getCurrentName();

do {
String relaxedName = getRelaxedName(propName);
String mappedName = properties.get(relaxedName);
defaultImplementation(p, ctxt, bean, mappedName);
} while ((propName = p.nextFieldName()) != null);
}
return bean;
}

private void defaultImplementation(JsonParser p, DeserializationContext ctxt, Object bean, String propName) throws IOException {
p.nextToken();
SettableBeanProperty prop = _beanProperties.find(propName);

if (prop != null) { // normal case
try {
prop.deserializeAndSet(p, ctxt, bean);
} catch (Exception e) {
wrapAndThrow(e, bean, propName, ctxt);
}
return;
}
handleUnknownVanilla(p, ctxt, bean, propName);
}

private String getRelaxedName(String name) {
return name.replaceAll("[_\\-]", "").toLowerCase();
}
}

上面的代码打印:

DeserializeIt{fieldOne='value1', fieldOneAndHalf='value15', fieldTwo='value2', fieldThree='value3', fieldFour='value4'}

另请参阅:

关于java - "Relaxed"Jackson 的字段名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55846834/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com