2017-02-07 14 views
0

Я пытаюсь создать следующий JSON динамически на основе ввода PARAMS т.е. (версия содержания, в списке содержимых идентификаторов)Java + Джексон: Как сериализовать объект, содержащий массив/список других объектов

{ 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "term": { 
      "version": { 
       "value": "published" 
      } 
      } 
     }, 
     { 
      "terms": { 
      "contentId": [ 
      "contentId-123", 
      "contentId-456" 
      ] 
      } 
     } 
     ] 
    } 
    } 
} 

Вышеупомянутый json - это тело запроса для запроса удаления с помощью эластичного поиска. version и contentId, упомянутые в приведенных выше json, являются действительными полями/атрибутами объекта контента или модели данных.

Я получаю это исключение при сериализации объекта:

com.fasterxml.jackson.core.JsonGenerationException: Can not start an object, expecting field name 
    at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1886) 
    at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator._verifyPrettyValueWrite(WriterBasedJsonGenerator.java:832) 
    at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator._verifyValueWrite(WriterBasedJsonGenerator.java:797) 
    at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator.writeStartObject(WriterBasedJsonGenerator.java:268) 
    at com.cdk.dmg.services.sitecontent.util.ConstantsTest$DeleteQuerySerializer.serialize(Test.java:200) 
    at com.cdk.dmg.services.sitecontent.util.ConstantsTest$DeleteQuerySerializer.serialize(Test.java:183) 
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292) 
    at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1419) 
    at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1147) 
    at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1020) 

Вот мой код:

class SearchParam { 
    boolean isMultivalued; 
    String fieldName; 
    String value; 
    List<String> values; 

    @Override 
    public String toString() { 
     final StringBuilder sb = new StringBuilder("SearchParam{"); 
     sb.append("isMultivalued=").append(isMultivalued); 
     sb.append(", fieldName='").append(fieldName).append('\''); 
     sb.append(", value='").append(value).append('\''); 
     sb.append(", values=").append(values); 
     sb.append('}'); 
     return sb.toString(); 
    } 
} 

class DeleteQuery { 
    List<SearchParam> mustParams; 
} 

class DeleteQuerySerializer extends StdSerializer<DeleteQuery> { 

    protected DeleteQuerySerializer(Class<DeleteQuery> t) { 
     super(t); 
    } 

    public DeleteQuerySerializer() { 
     this(null); 
    } 

    @Override 
    public void serialize(DeleteQuery value, JsonGenerator jsonGen, SerializerProvider provider) throws IOException { 
     jsonGen.writeStartObject(); 
     jsonGen.writeObjectFieldStart("query"); 
     jsonGen.writeObjectFieldStart("bool"); 
     jsonGen.writeArrayFieldStart("must"); 
     for (SearchParam param : value.mustParams) { 
      jsonGen.writeObject(param); 
     } 
     jsonGen.writeEndObject(); 
    } 
} 

class SearchParamSerializer extends StdSerializer<SearchParam> { 

    protected SearchParamSerializer(Class<SearchParam> t) { 
     super(t); 
    } 

    protected SearchParamSerializer() { 
     this(null); 
    } 

    @Override 
    public void serialize(SearchParam value, JsonGenerator jsonGen, SerializerProvider provider) throws IOException, JsonGenerationException { 
     jsonGen.writeStartObject(); 
     if (value.isMultivalued) { 
      jsonGen.writeObjectFieldStart("terms"); 
      jsonGen.writeArrayFieldStart(value.fieldName); 
      for (String v : value.values) { 
       jsonGen.writeString(v); 
      } 
      jsonGen.writeEndArray(); 
     } else { 
      jsonGen.writeObjectFieldStart("term"); 
      jsonGen.writeObjectFieldStart(value.fieldName); 
      jsonGen.writeStringField("value", value.value); 
     } 
     jsonGen.writeEndObject(); 
    } 
} 

@Test 
public void dummyTest() throws JsonProcessingException { 

    SearchParam versionParam = new SearchParam(); 
    versionParam.fieldName = "version"; 
    versionParam.isMultivalued = false; 
    versionParam.value = "published"; 

    SearchParam idParam = new SearchParam(); 
    idParam.fieldName = "contentId"; 
    idParam.isMultivalued = true; 
    idParam.values = Arrays.asList("contentID-1", "contentID-2", "contentID-3"); 

    List<SearchParam> mustParams = Arrays.asList(versionParam, idParam); 

    ObjectMapper mapper = new ObjectMapper(); 

    SimpleModule module = new SimpleModule(); 
    module.addSerializer(SearchParam.class, new SearchParamSerializer()); 
    module.addSerializer(DeleteQuery.class, new DeleteQuerySerializer()); 
    mapper.registerModule(module); 

    DeleteQuery deleteQuery = new DeleteQuery(); 
    deleteQuery.mustParams = mustParams; 

    String serialized = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(deleteQuery); 
    System.out.println(serialized); 
} 

Ссылка: jackson-custom-serialization

я немножко твики в коде (например, внутри SearchParamSerializer.serialize(), перегруппированы jsonGen.writeStartObject() и jsonGen.writeEndObject() относительно value.isMultivalued()), но все равно не получится, как ожидалось.

После многократного переполнения и переполнения стека я получил несколько ссылок, но они больше говорят о библиотеке Gson и/или находятся на python.

Любая помощь!

ответ

0

К сожалению, вы имели дело с этим API: https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html?

+0

Да. Но у нас есть другой проект, основанный на java API-интерфейсе flex-поиска, и мы должны это использовать. Я не могу напрямую использовать API-интерфейс QueryBuilder для java API. Более того, этот проект отличается от моего или нашей команды. – manoj

+0

Я собираюсь взглянуть на ваш код. –

0

Мое обходное решение для продолжения.

Модифицированный DeleteQuery и DeleteQuerySerializer, как показано ниже:

class DeleteQuery { 
    List<String> mustParams; 
} 

class DeleteQuerySerializer extends StdSerializer<DeleteQuery> { 

    protected DeleteQuerySerializer(Class<DeleteQuery> t) { 
     super(t); 
    } 

    public DeleteQuerySerializer() { 
     this(null); 
    } 

    @Override 
    public void serialize(DeleteQuery value, JsonGenerator jsonGen, SerializerProvider provider) throws IOException { 
     jsonGen.writeStartObject(); 
     jsonGen.writeObjectFieldStart("query"); 
     jsonGen.writeObjectFieldStart("bool"); 
     String mustParam = String.join(",", value.mustParams); 
     jsonGen.writeFieldName("must"); 
     jsonGen.writeRawValue("[" + mustParam + "]"); 
     jsonGen.writeEndObject(); 
    } 
} 

И вот dummyTest():

public void dummyTest() throws IOException { 
    System.out.println(); 

    SearchParam versionParam = new SearchParam(); 
    versionParam.fieldName = "version"; 
    versionParam.isMultivalued = false; 
    versionParam.value = "published"; 

    SearchParam idParam = new SearchParam(); 
    idParam.fieldName = "contentId"; 
    idParam.isMultivalued = true; 
    idParam.values = Arrays.asList("contentId-123", "contentId-456", "xyz"); 

    List<SearchParam> mustParams = Arrays.asList(versionParam, idParam); 

    ObjectMapper mapper = new ObjectMapper(); 

    SimpleModule module = new SimpleModule(); 
    module.addSerializer(SearchParam.class, new SearchParamSerializer()); 
    module.addSerializer(DeleteQuery.class, new DeleteQuerySerializer()); 
    mapper.registerModule(module); 

    List<String> mustParamList = new ArrayList<>(); 
    for (SearchParam param : mustParams) { 
     mustParamList.add(mapper.writeValueAsString(param)); 
    } 

    DeleteQuery deleteQuery = new DeleteQuery(); 
    deleteQuery.mustParams = mustParamList; 

    String serialized = mapper.writeValueAsString(deleteQuery); 
    JsonNode jsonNode = mapper.readTree(serialized); 
    String s = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode); 
    System.out.println(s); 
} 

Наконец, получил этот результат:

{ 
    "query": { 
     "bool": { 
      "must": [{ 
       "term": { 
        "version": { 
         "value": "published" 
        } 
       } 
      }, { 
       "terms": { 
        "contentId": ["contentId-123", "contentId-456", "xyz"] 
       } 
      }] 
     } 
    } 
} 

:)

Это не правильное решение, но да, я сейчас разблокирован и могу продолжать дальше. :)

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

  • Нет связанных вопросов^_^