2013-08-30 3 views
0

У меня есть класс Java, как:Изменение Json имя ключа динамически - Джексон

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

Теперь во время выполнения я хочу дать разные имена свойств для каждого объекта, а не статичным, используя @JsonProperty (» образец ")

Как это сделать? Я использую Джексон библиотеки объявления Spring MVC

Спасибо заранее ...

+0

Некоторые контекст, почему вы хотите, чтобы сделать это было бы полезно. Я сомневаюсь, что это возможно с помощью аннотаций Джексона. Вероятно, вам придется предоставить собственный сериализатор. –

+0

Я думаю, что единственным способом будет пользовательский сериализатор. Я думаю, это может помочь: http://techtraits.com/Programming/2011/11/20/using-custom-serializers-with-jackson/ – CodeChimp

+0

Помог ли ниже ответ? Я только хотел узнать. Если нет, можете ли вы рассказать мне о проблеме, с которой вы столкнулись? –

ответ

3

Вы можете использовать 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. Вы можете получить конвертер сообщений Jackson HTTP из контекста весеннего приложения и получить его объект mapper.

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

И все. Это самый простой способ динамического изменения сериализации ваших свойств.

Чтобы использовать это, создайте List из PropertyNameMappers и добавьте его в качестве атрибута (с именем «nameMappings» в этом примере) в текущем запросе.

Это пример, а не готовый к производству код. Возможно, вам, вероятно, потребуется добавить нулевые проверки и все такое. Кроме того, может потребоваться несколько небольших настроек, основанных на версии библиотек, которые вы используете.

Если решение не подходит для вас, сообщите мне о проблемах, с которыми вы сталкиваетесь.

1

Вы можете ввести пользовательскую 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 
    } 

Наконец, вы должны создать экземпляр и ввести его во время выполнения. объектMapper.setNamingStrategy (myNamingStrategyInstance));

Посмотреть этот пост Cowtowncoder больше на PropertyNamingStrategy:

Jackson 1.8: custom property naming strategies

Или эта документация:

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

Смежные вопросы