2014-12-15 4 views
4

Я хотел бы знать, если это возможно настроить десериализацию JSON в зависимости имени поля, напримерДжексон, пользовательские десериализации для конкретных имен полого

{ 
    id: "abc123", 
    field1: {...} 
    other: { 
     field1: {....} 
    } 
} 

I предыдущего JSON, я хотел бы иметь настраиваемый десериализатор для полей с именем «field1» на любом уровне json.

Причина: У нас есть данные, сохраненные как JSON, и у нас есть служба REST, которая возвращает такие данные, но перед ее возвратом служба должна добавить дополнительную информацию в атрибут «field1».

Типы очень динамичны, поэтому мы не можем определить класс Java для сопоставления json для использования аннотаций.

Первым подходом было десериализовать Map.class, а затем использовать JsonPath для поиска шаблона $ .. field1, но этот процесс дорог для больших объектов.

Я ценю любую помощь.

Спасибо,

Edwin Miguel

+0

Это https://stackoverflow.com/a/41002122/2954288 поможет, если вы можете и хотите аннотировать объект читается в. – Harald

ответ

0

создать пользовательский десериализатор и добавить его в SimpleModule для ObjectMapper

public class CustomDeserializer extends StdDeserializer<Map> { 
public CustomDeserializer() { 
    super(Map.class); 
} 

@Override 
public Map deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
    Map<String, Object> result = new HashMap<String, Object>(); 
    jp.nextToken(); 
    while (!JsonToken.END_OBJECT.equals(jp.getCurrentToken())) { 
     String key = jp.getText(); 
     jp.nextToken(); 
     if ("field1".equals(key)) { 
      MyObject fiedlObj= jp.readValueAs(MyObject.class); 
      //inject extra info 
      //... 
      result.put(key, fieldObj); 
     } else { 
      if (JsonToken.START_OBJECT.equals(jp.getCurrentToken())) { 
       result.put(key, deserialize(jp, ctxt)); 
      } else if (JsonToken.START_ARRAY.equals(jp.getCurrentToken())) { 
       jp.nextToken(); 
       List<Object> linkedList = new LinkedList<Object>(); 
       while (!JsonToken.END_ARRAY.equals(jp.getCurrentToken())) { 
        linkedList.add(deserialize(jp, ctxt)); 
        jp.nextToken(); 
       } 
       result.put(key, linkedList); 
      } else { 
       result.put(key, jp.readValueAs(Object.class)); 
      } 
     } 
     jp.nextToken(); 
    } 
    return result; 
} 

} 

Проблема заключается в том, что я должен был осуществлять синтаксический анализ для остальных атрибутов.

На данный момент, это мое решение ...

+0

Не можете ли вы делегировать существующий десериализатор, а не писать весь десериализационный код самостоятельно? –

+1

Я хотел бы делегировать, но я не уверен, как это сделать. Возможно, расширение MapSerializer, но я не уверен, как передать необходимые параметры конструктору. –

2

Вы должны рассмотреть регистрации custom deserializer с ObjectMapper для этой цели.

Тогда вы должны просто сопоставить свой поток JSON с Map<String, Object>, зная, что ваши объекты field1 будут обрабатываться вашим пользовательским кодом.

+0

Спасибо за Йор ответ, но как Джексон знает, когда использовать пользовательский десериализатор, если я сопоставляюсь с Map ?, я имею в виду, что нет способа (я думаю) знать целевой объект, если не существует определения собственного класса java , –

+0

Я только что создал пользовательский десериализатор и зарегистрировал его для Map.class. На данный момент проблема в том, что мне нужно обрабатывать всю десериализацию объекта. –

+0

Что я имел в виду, так это то, что ваш десериализатор будет знать о позиции в документе и только принял действие, если текущее поле было 'field1', иначе делегируйте' super' или что-то еще. Я просто надеюсь, что я не предлагал невозможный подход ... –

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