Skip to content

Commit

Permalink
Fully Support Null Fields when Using Custom ObjectSerializer (#29238)
Browse files Browse the repository at this point in the history
Fully Support Null Fields when Using Custom ObjectSerializer
  • Loading branch information
alzimmermsft authored Jun 7, 2022
1 parent 9d4a450 commit 1710bc4
Show file tree
Hide file tree
Showing 14 changed files with 263 additions and 56 deletions.
2 changes: 2 additions & 0 deletions sdk/search/azure-search-documents/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### Bugs Fixed

- Fixed a bug where a custom `ObjectSerializer`'s output wasn't being respected in regard to null field values. ([#29238](https://github.com/Azure/azure-sdk-for-java/pull/29238))

### Other Changes

## 11.4.10 (2022-05-12)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,11 @@
import com.azure.search.documents.models.ScoringStatistics;
import com.azure.search.documents.models.SearchMode;
import com.azure.search.documents.models.SuggestOptions;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import reactor.core.publisher.Mono;

/** An instance of this class provides access to all the operations defined in Documents. */
Expand Down Expand Up @@ -401,21 +399,19 @@ public Mono<Response<SearchDocumentsResult>> searchGetWithResponseAsync(
}
UUID xMsClientRequestId = xMsClientRequestIdInternal;
List<String> facetsConverted =
Optional.ofNullable(facets)
.map(Collection::stream)
.orElseGet(Stream::empty)
.map((item) -> Objects.toString(item, ""))
.collect(Collectors.toList());
(facets == null)
? new ArrayList<>()
: facets.stream().map(item -> Objects.toString(item, "")).collect(Collectors.toList());
String highlightFieldsConverted =
JacksonAdapter.createDefaultSerializerAdapter().serializeList(highlightFields, CollectionFormat.CSV);
String orderByConverted =
JacksonAdapter.createDefaultSerializerAdapter().serializeList(orderBy, CollectionFormat.CSV);
List<String> scoringParametersConverted =
Optional.ofNullable(scoringParameters)
.map(Collection::stream)
.orElseGet(Stream::empty)
.map((item) -> Objects.toString(item, ""))
.collect(Collectors.toList());
(scoringParameters == null)
? new ArrayList<>()
: scoringParameters.stream()
.map(item -> Objects.toString(item, ""))
.collect(Collectors.toList());
String searchFieldsConverted =
JacksonAdapter.createDefaultSerializerAdapter().serializeList(searchFields, CollectionFormat.CSV);
String selectConverted =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
import com.azure.core.util.serializer.SerializerEncoding;
import com.azure.search.documents.models.IndexAction;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import static com.azure.search.documents.implementation.util.Utility.MAP_STRING_OBJECT_TYPE_REFERENCE;
import static com.azure.search.documents.implementation.util.Utility.getDefaultSerializerAdapter;

/**
Expand Down Expand Up @@ -52,26 +51,42 @@ public static <T> com.azure.search.documents.implementation.models.IndexAction m
com.azure.search.documents.implementation.models.IndexAction indexAction =
new com.azure.search.documents.implementation.models.IndexAction().setActionType(obj.getActionType());

Map<String, Object> mapProperties = IndexActionHelper.getProperties(obj);
if (mapProperties == null) {
T properties = obj.getDocument();
if (serializer == null) {
try {
String serializedJson = getDefaultSerializerAdapter().serialize(properties,
SerializerEncoding.JSON);
mapProperties = getDefaultSerializerAdapter().deserialize(serializedJson,
MAP_STRING_OBJECT_TYPE_REFERENCE.getJavaType(), SerializerEncoding.JSON);
} catch (IOException ex) {
throw LOGGER.logExceptionAsError(
new RuntimeException("Failed to serialize IndexAction.", ex));
}
// Attempt to get the document as the Map<String, Object> properties.
Object document = IndexActionHelper.getProperties(obj);
if (document == null) {
// If ths document wasn't a Map type, get the generic document type.
document = obj.getDocument();
}

// Convert the document to the JSON string representation.
String documentJson;
if (serializer == null) {
// A custom ObjectSerializer isn't being used, fallback to default JacksonAdapter.
try {
documentJson = getDefaultSerializerAdapter().serialize(document, SerializerEncoding.JSON);
} catch (IOException ex) {
throw LOGGER.logExceptionAsError(new UncheckedIOException(ex));
}
} else {
// A custom ObjectSerializer is being used, use it.
documentJson = new String(serializer.serializeToBytes(document), StandardCharsets.UTF_8);
}

if (documentJson != null) {
boolean startsWithCurlyBrace = documentJson.startsWith("{");
boolean endsWithCurlyBrace = documentJson.endsWith("}");

if (startsWithCurlyBrace && endsWithCurlyBrace) {
indexAction.setRawDocument(documentJson.substring(1, documentJson.length() - 1));
} else if (startsWithCurlyBrace) {
indexAction.setRawDocument(documentJson.substring(1));
} else if (endsWithCurlyBrace) {
indexAction.setRawDocument(documentJson.substring(0, documentJson.length() - 1));
} else {
mapProperties = serializer.deserializeFromBytes(serializer.serializeToBytes(properties),
MAP_STRING_OBJECT_TYPE_REFERENCE);
indexAction.setRawDocument(documentJson);
}
}

indexAction.setAdditionalProperties(mapProperties);
return indexAction;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// Code generated by Microsoft (R) AutoRest Code Generator.
// Changes may cause incorrect behavior and will be lost if the code is
// regenerated.

package com.azure.search.documents.implementation.models;

import com.azure.core.annotation.Fluent;
Expand All @@ -13,12 +12,15 @@
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.HashMap;
import java.util.Map;

/** Represents an index action that operates on a document. */
@Fluent
@JsonSerialize(using = IndexActionSerializer.class)
public final class IndexAction {

/*
* The operation to perform on a document in an indexing batch.
*/
Expand Down Expand Up @@ -78,4 +80,26 @@ void setAdditionalProperties(String key, Object value) {
}
additionalProperties.put(key, value);
}

@JsonIgnore private String rawDocument;

/**
* Gets the raw JSON document.
*
* @return The raw JSON document.
*/
public String getRawDocument() {
return rawDocument;
}

/**
* Sets the raw JSON document.
*
* @param rawDocument The raw JSON document.
* @return the IndexAction object itself.
*/
public IndexAction setRawDocument(String rawDocument) {
this.rawDocument = rawDocument;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.search.documents.implementation.models;

import com.azure.core.util.CoreUtils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

/**
* Serializes an {@link IndexAction}.
*/
public final class IndexActionSerializer extends JsonSerializer<IndexAction> {
@Override
public void serialize(IndexAction value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value != null) {
gen.writeStartObject();
gen.writeStringField("@search.action", value.getActionType().toString());

String rawDocument = value.getRawDocument();
if (!CoreUtils.isNullOrEmpty(rawDocument)) {
gen.writeRaw(',');
gen.writeRaw(rawDocument);
}

gen.writeEndObject();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public final class IndexAction<T> {
private Map<String, Object> properties;

/*
* The operation to perform on a document in an indexing batch. Possible
* values include: 'Upload', 'Merge', 'MergeOrUpload', 'Delete'
* The operation to perform on a document in an indexing batch.
*/
@JsonProperty(value = "@search.action")
private IndexActionType actionType;
Expand All @@ -45,8 +44,10 @@ public <U> Map<String, Object> getProperties(IndexAction<U> indexAction) {
}
});
}

/**
* Get the document on which the action will be performed; Fields other than the key are ignored for delete actions.
* Get the document on which the action will be performed; Fields other than the key are ignored for delete
* actions.
*
* @return the document value.
*/
Expand All @@ -59,7 +60,8 @@ public T getDocument() {
}

/**
* Get the document on which the action will be performed; Fields other than the key are ignored for delete actions.
* Get the document on which the action will be performed; Fields other than the key are ignored for delete
* actions.
*
* @param document the document value to set.
* @return the IndexAction object itself.
Expand All @@ -77,9 +79,7 @@ public IndexAction<T> setDocument(T document) {
}

/**
* Get the actionType property: The operation to perform on a document in
* an indexing batch. Possible values include: 'Upload', 'Merge',
* 'MergeOrUpload', 'Delete'.
* Get the actionType property: The operation to perform on a document in an indexing batch.
*
* @return the actionType value.
*/
Expand All @@ -88,9 +88,7 @@ public IndexActionType getActionType() {
}

/**
* Set the actionType property: The operation to perform on a document in
* an indexing batch. Possible values include: 'Upload', 'Merge',
* 'MergeOrUpload', 'Delete'.
* Set the actionType property: The operation to perform on a document in an indexing batch.
*
* @param actionType the actionType value to set.
* @return the IndexAction object itself.
Expand All @@ -101,8 +99,7 @@ public IndexAction<T> setActionType(IndexActionType actionType) {
}

/**
* The private setter to set the properties property
* via {@link IndexActionHelper.IndexActionAccessor}.
* The private setter to set the properties via {@link IndexActionHelper.IndexActionAccessor}.
*
* @param properties The properties.
*/
Expand All @@ -111,11 +108,11 @@ private void setProperties(Map<String, Object> properties) {
}

/**
* The private getter to get the properties property
* via {@link IndexActionHelper.IndexActionAccessor}.
* The private getter to get the properties via {@link IndexActionHelper.IndexActionAccessor}.
*
* @return The properties
*/
private Map<String, Object> getProperties() {
return this.properties;
return this.properties;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public static QueryAnswerType fromString(String name) {
return fromString(name, QueryAnswerType.class);
}

/** @return known QueryAnswerType values. */
/**
* Gets known QueryAnswerType values.
*
* @return known QueryAnswerType values.
*/
public static Collection<QueryAnswerType> values() {
return values(QueryAnswerType.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public static QueryCaptionType fromString(String name) {
return fromString(name, QueryCaptionType.class);
}

/** @return known QueryCaptionType values. */
/**
* Gets known QueryCaptionType values.
*
* @return known QueryCaptionType values.
*/
public static Collection<QueryCaptionType> values() {
return values(QueryCaptionType.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,11 @@ public static QueryLanguage fromString(String name) {
return fromString(name, QueryLanguage.class);
}

/** @return known QueryLanguage values. */
/**
* Gets known QueryLanguage values.
*
* @return known QueryLanguage values.
*/
public static Collection<QueryLanguage> values() {
return values(QueryLanguage.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public static QuerySpellerType fromString(String name) {
return fromString(name, QuerySpellerType.class);
}

/** @return known QuerySpellerType values. */
/**
* Gets known QuerySpellerType values.
*
* @return known QuerySpellerType values.
*/
public static Collection<QuerySpellerType> values() {
return values(QuerySpellerType.class);
}
Expand Down
Loading

0 comments on commit 1710bc4

Please sign in to comment.