【问题标题】:Change Json key name dynamically - Jackson动态更改 Json 密钥名称 - Jackson
【发布时间】:2013-08-30 10:59:14
【问题描述】:

我有一个类似的 java 类:

class TestJsonClass {
    private String propertyA;
    private String propertyB;
    private String propertyC;
}

现在在运行时我想为每个属性指定不同的属性名称,而不是使用 @JsonProperty("sample") 的静态名称

我该如何做到这一点?我正在使用 Jackson 库广告 Spring MVC

提前谢谢...

【问题讨论】:

  • 有关您为什么要这样做的一些上下文会有所帮助。我怀疑是否有可能使用杰克逊的注释。您可能必须提供自定义序列化程序。
  • 我认为唯一的方法是自定义序列化程序。我认为这可能会有所帮助:techtraits.com/Programming/2011/11/20/…
  • 以下答案是否有帮助?我只是想知道。如果没有,你能告诉我你面临的问题吗?

标签: java json spring-mvc jackson


【解决方案1】:

您可以为此目的使用Modules。这是解决您的问题的最简单方法。这是一个例子:

一个简单的类,可以为每个请求携带您的属性名称映射:

public class PropertyNameMapper {
    // The class for which the mappings need to take place.
    public Class<?> classToFilter;
    // The mappings property names. Key would be the existing property name
    // value would be name you want in the ouput.
    public Map<String, String> nameMappings = Collections.emptyMap();

    public PropertyNameMapper(Class<?> classToFilter, Map<String, String> nameMappings) {
        this.classToFilter = classToFilter;
        this.nameMappings = nameMappings;
    }
}

自定义BeanPropertyWriter,用于指定属性的输出名称。

public class MyBeanPropertyWriter extends BeanPropertyWriter {
    // We would just use the copy-constructor rather than modifying the
    // protected properties. This is more in line with the current design
    // of the BeanSerializerModifier class (according to its documentation).
    protected MyBeanPropertyWriter(BeanPropertyWriter base, String targetName) {
        super(base, new SerializedString(targetName));
    }

}

现在,每次调用自定义BeanSerializerModifier 以允许您修改序列化属性。

public class MySerializerModifier extends BeanSerializerModifier {

    public List<BeanPropertyWriter> changeProperties(
            SerializationConfig config, BeanDescription beanDesc,
            List<BeanPropertyWriter> beanProperties) {

        List<PropertyNameMapper> propertyMappings = getNameMappingsFromRequest();
        PropertyNameMapper mapping = mappingsForClass(propertyMappings,
                beanDesc.getBeanClass());

        if (mapping == null) {
            return beanProperties;
        }

        List<BeanPropertyWriter> propsToWrite = new ArrayList<BeanPropertyWriter>();
        for (BeanPropertyWriter propWriter : beanProperties) {
            String propName = propWriter.getName();
            String outputName = mapping.nameMappings.get(propName);
            if (outputName != null) {
                BeanPropertyWriter modifiedWriter = new MyBeanPropertyWriter(
                        propWriter, outputName);
                propsToWrite.add(modifiedWriter);
            } else {
                propsToWrite.add(propWriter);
            }
        }
        return propsToWrite;
    }

    private List<PropertyNameMapper> getNameMappingsFromRequest() {
        RequestAttributes requestAttribs = RequestContextHolder
                .getRequestAttributes();
        List<PropertyNameMapper> nameMappings = (List<PropertyNameMapper>) requestAttribs
                .getAttribute("nameMappings",
                        RequestAttributes.SCOPE_REQUEST);
        return nameMappings;
    }

    private PropertyNameMapper mappingsForClass(
            List<PropertyNameMapper> nameMappings, Class<?> beanClass) {
        for (PropertyNameMapper mapping : nameMappings) {
            if (mapping.classToFilter.equals(beanClass)) {
                return mapping;
            }
        }
        return null;
    }
}

现在,您需要一个自定义 Module 才能使用上面创建的 BeanSerializerModifier 自定义输出:

public class MyModule extends Module {

    @Override
    public String getModuleName() {
        return "Test Module";
    }

    @Override
    public void setupModule(SetupContext context) {
        context.addBeanSerializerModifier(new MySerializerModifier());
    }

    @Override
    public Version version() {
        // Modify if you need to.
        return Version.unknownVersion();
    }
}

现在使用您的ObjectMapper 注册此模块。您可以从 Spring 应用程序上下文中获取 Jackson HTTP 消息转换器,并获取其对象映射器。

// Figure out a way to get the ObjectMapper.
MappingJackson2HttpMessageConverter converter = ... // get the jackson-mapper;
converter.getObjectMapper().registerModule(new MyModule())

就是这样。这是动态自定义属性序列化的最简单方法。

要使用它,请创建 PropertyNameMappersList 并将其添加为当前请求中的属性(在本例中名为“nameMappings”)。

这是一个示例,不是生产就绪代码。您可能需要添加空检查和类似的东西。此外,根据您使用的库版本,可能需要进行一些小的调整。

如果解决方案对您不起作用,请告诉我您面临的问题。

【讨论】:

    【解决方案2】:

    您可以将自定义 PropertyNamingStrategy 注入反序列化中使用的 ObjectMapper。

    只需在运行时将字段设置到 PropertyNamingStrategy,假设您可以将它们映射到默认 JsonPropertyName 之类的东西(例如 propertyA、propertyB、propertyC)。

    public class MyNamingStrategy extends PropertyNamingStrategy {
    
        String propertyAName, propertyBName, propertyCName;
    
        public MyNamingStrategy(String propANm, String propBNm, String propCNm) {
            this.propertyAName = propANm;
            //finish
        }
    
        @Override
        public String nameForField(MapperConfig<?> config, AnnotatedField field,
                String defaultName) {
            return convert(defaultName);
        }
    
        @Override
        public String nameForGetterMethod(MapperConfig<?> config,
                AnnotatedMethod method, String defaultName) {
            return convert(defaultName);
        }
    
        @Override
        public String nameForSetterMethod(MapperConfig<?> config,
                AnnotatedMethod method, String defaultName) {
            return convert(defaultName);
        }
    
        public String convert(String defaultName ){
            return defaultName.replace("propertyA", propertyAName).replace( //finish
        }
    

    最后,您将创建一个实例并在运行时注入它。 objectMapper.setNamingStrategy(myNamingStrategyInstance));

    有关 PropertyNamingStrategy 的更多信息,请参阅此 Cowtowncoder 帖子:

    Jackson 1.8: custom property naming strategies

    或者这个文档:

    github.com/FasterXML/jackson-docs/wiki/PropertyNamingStrategy

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多