diff --git a/components/abstractions/android/build.gradle b/components/abstractions/android/build.gradle
index 818e02384..63ed0cd21 100644
--- a/components/abstractions/android/build.gradle
+++ b/components/abstractions/android/build.gradle
@@ -57,6 +57,7 @@ android {
disable "GradleDependency"
disable "NewerVersionAvailable"
disable "DuplicatePlatformClasses" // xpp3 added by azure-identity
+ disable "LambdaLast" // Wrongly enforced in KiotaJsonSerialization helpers
}
sourceSets {
main {
diff --git a/components/abstractions/gradle/dependencies.gradle b/components/abstractions/gradle/dependencies.gradle
index 63a4ce8b0..8f63f9354 100644
--- a/components/abstractions/gradle/dependencies.gradle
+++ b/components/abstractions/gradle/dependencies.gradle
@@ -3,6 +3,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.2'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.2'
testImplementation 'org.mockito:mockito-core:5.14.1'
+ testImplementation project(':components:serialization:json')
// Use JUnit Jupiter Engine for testing.
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
diff --git a/components/abstractions/spotBugsExcludeFilter.xml b/components/abstractions/spotBugsExcludeFilter.xml
index e2dbb38ce..68e65df88 100644
--- a/components/abstractions/spotBugsExcludeFilter.xml
+++ b/components/abstractions/spotBugsExcludeFilter.xml
@@ -46,13 +46,11 @@ xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubu
-
-
-
-
+
+
diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java
index 046c81019..ddf229f88 100644
--- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java
+++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaJsonSerialization.java
@@ -26,6 +26,20 @@ private KiotaJsonSerialization() {}
return KiotaSerialization.serializeAsStream(CONTENT_TYPE, value);
}
+ /**
+ * Serializes the given value to a stream
+ * @param the type of the value to serialize
+ * @param value the value to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a stream
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static InputStream serializeAsStream(
+ @Nonnull final T value, final boolean serializeOnlyChangedValues) throws IOException {
+ return KiotaSerialization.serializeAsStream(
+ CONTENT_TYPE, value, serializeOnlyChangedValues);
+ }
+
/**
* Serializes the given value to a string
* @param the type of the value to serialize
@@ -38,6 +52,20 @@ private KiotaJsonSerialization() {}
return KiotaSerialization.serializeAsString(CONTENT_TYPE, value);
}
+ /**
+ * Serializes the given value to a string
+ * @param the type of the value to serialize
+ * @param value the value to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a string
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static String serializeAsString(
+ @Nonnull final T value, final boolean serializeOnlyChangedValues) throws IOException {
+ return KiotaSerialization.serializeAsString(
+ CONTENT_TYPE, value, serializeOnlyChangedValues);
+ }
+
/**
* Serializes the given value to a stream
* @param the type of the value to serialize
@@ -50,6 +78,21 @@ private KiotaJsonSerialization() {}
return KiotaSerialization.serializeAsStream(CONTENT_TYPE, values);
}
+ /**
+ * Serializes the given value to a stream
+ * @param the type of the value to serialize
+ * @param values the values to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a stream
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static InputStream serializeAsStream(
+ @Nonnull final Iterable values, final boolean serializeOnlyChangedValues)
+ throws IOException {
+ return KiotaSerialization.serializeAsStream(
+ CONTENT_TYPE, values, serializeOnlyChangedValues);
+ }
+
/**
* Serializes the given value to a string
* @param the type of the value to serialize
@@ -62,6 +105,21 @@ private KiotaJsonSerialization() {}
return KiotaSerialization.serializeAsString(CONTENT_TYPE, values);
}
+ /**
+ * Serializes the given value to a string
+ * @param the type of the value to serialize
+ * @param values the values to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a string
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static String serializeAsString(
+ @Nonnull final Iterable values, final boolean serializeOnlyChangedValues)
+ throws IOException {
+ return KiotaSerialization.serializeAsString(
+ CONTENT_TYPE, values, serializeOnlyChangedValues);
+ }
+
/**
* Deserializes the given stream to a model object
* @param the type of the value to deserialize
diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java
index e7b06eb13..a9c0a9e0e 100644
--- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java
+++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/KiotaSerialization.java
@@ -16,6 +16,7 @@
*/
public final class KiotaSerialization {
private static final String CHARSET_NAME = "UTF-8";
+ private static final boolean DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES = true;
private KiotaSerialization() {}
@@ -29,7 +30,26 @@ private KiotaSerialization() {}
*/
@Nonnull public static InputStream serializeAsStream(
@Nonnull final String contentType, @Nonnull final T value) throws IOException {
- try (final SerializationWriter writer = getSerializationWriter(contentType, value)) {
+ return serializeAsStream(contentType, value, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES);
+ }
+
+ /**
+ * Serializes the given value to a stream and configures returned values by the backing store if available
+ * @param the type of the value to serialize
+ * @param contentType the content type to use for serialization
+ * @param value the value to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a stream
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static InputStream serializeAsStream(
+ @Nonnull final String contentType,
+ @Nonnull final T value,
+ final boolean serializeOnlyChangedValues)
+ throws IOException {
+ Objects.requireNonNull(value);
+ try (final SerializationWriter writer =
+ getSerializationWriter(contentType, serializeOnlyChangedValues)) {
writer.writeObjectValue("", value);
return writer.getSerializedContent();
}
@@ -45,7 +65,27 @@ private KiotaSerialization() {}
*/
@Nonnull public static String serializeAsString(
@Nonnull final String contentType, @Nonnull final T value) throws IOException {
- try (final InputStream stream = serializeAsStream(contentType, value)) {
+ Objects.requireNonNull(value);
+ return serializeAsString(contentType, value, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES);
+ }
+
+ /**
+ * Serializes the given value to a string
+ * @param the type of the value to serialize
+ * @param contentType the content type to use for serialization
+ * @param value the value to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a string
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static String serializeAsString(
+ @Nonnull final String contentType,
+ @Nonnull final T value,
+ final boolean serializeOnlyChangedValues)
+ throws IOException {
+ Objects.requireNonNull(value);
+ try (final InputStream stream =
+ serializeAsStream(contentType, value, serializeOnlyChangedValues)) {
return new String(Compatibility.readAllBytes(stream), CHARSET_NAME);
}
}
@@ -61,7 +101,27 @@ private KiotaSerialization() {}
@Nonnull public static InputStream serializeAsStream(
@Nonnull final String contentType, @Nonnull final Iterable values)
throws IOException {
- try (final SerializationWriter writer = getSerializationWriter(contentType, values)) {
+ Objects.requireNonNull(values);
+ return serializeAsStream(contentType, values, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES);
+ }
+
+ /**
+ * Serializes the given value to a stream
+ * @param the type of the value to serialize
+ * @param contentType the content type to use for serialization
+ * @param values the values to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a stream
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static InputStream serializeAsStream(
+ @Nonnull final String contentType,
+ @Nonnull final Iterable values,
+ final boolean serializeOnlyChangedValues)
+ throws IOException {
+ Objects.requireNonNull(values);
+ try (final SerializationWriter writer =
+ getSerializationWriter(contentType, serializeOnlyChangedValues)) {
writer.writeCollectionOfObjectValues("", values);
return writer.getSerializedContent();
}
@@ -78,20 +138,39 @@ private KiotaSerialization() {}
@Nonnull public static String serializeAsString(
@Nonnull final String contentType, @Nonnull final Iterable values)
throws IOException {
- try (final InputStream stream = serializeAsStream(contentType, values)) {
+ Objects.requireNonNull(values);
+ return serializeAsString(contentType, values, DEFAULT_SERIALIZE_ONLY_CHANGED_VALUES);
+ }
+
+ /**
+ * Serializes the given value to a string
+ * @param the type of the value to serialize
+ * @param contentType the content type to use for serialization
+ * @param values the values to serialize
+ * @param serializeOnlyChangedValues whether to serialize all values in value if value is a BackedModel
+ * @return the serialized value as a string
+ * @throws IOException when the stream cannot be closed or read.
+ */
+ @Nonnull public static String serializeAsString(
+ @Nonnull final String contentType,
+ @Nonnull final Iterable values,
+ final boolean serializeOnlyChangedValues)
+ throws IOException {
+ Objects.requireNonNull(values);
+ try (final InputStream stream =
+ serializeAsStream(contentType, values, serializeOnlyChangedValues)) {
return new String(Compatibility.readAllBytes(stream), CHARSET_NAME);
}
}
private static SerializationWriter getSerializationWriter(
- @Nonnull final String contentType, @Nonnull final Object value) {
+ @Nonnull final String contentType, final boolean serializeOnlyChangedValues) {
Objects.requireNonNull(contentType);
- Objects.requireNonNull(value);
if (contentType.isEmpty()) {
throw new NullPointerException("content type cannot be empty");
}
return SerializationWriterFactoryRegistry.defaultInstance.getSerializationWriter(
- contentType);
+ contentType, serializeOnlyChangedValues);
}
/**
diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java
index 0c4b5879c..9fcb2cb23 100644
--- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java
+++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterFactoryRegistry.java
@@ -1,6 +1,9 @@
package com.microsoft.kiota.serialization;
+import com.microsoft.kiota.store.BackingStoreSerializationWriterProxyFactory;
+
import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
import java.util.HashMap;
import java.util.Objects;
@@ -32,24 +35,77 @@ public SerializationWriterFactoryRegistry() {
@Override
@Nonnull public SerializationWriter getSerializationWriter(@Nonnull final String contentType) {
+ return getSerializationWriter(contentType, true);
+ }
+
+ /**
+ * Get a Serialization Writer with backing store configured with serializeOnlyChangedValues
+ * @param contentType
+ * @param serializeOnlyChangedValues control backing store functionality
+ * @return the serialization writer
+ * @throws RuntimeException when no factory is found for content type
+ */
+ @Nonnull public SerializationWriter getSerializationWriter(
+ @Nonnull final String contentType, final boolean serializeOnlyChangedValues) {
Objects.requireNonNull(contentType, "parameter contentType cannot be null");
if (contentType.isEmpty()) {
throw new NullPointerException("contentType cannot be empty");
}
- final String vendorSpecificContentType = contentType.split(";")[0];
- if (contentTypeAssociatedFactories.containsKey(vendorSpecificContentType)) {
- return contentTypeAssociatedFactories
- .get(vendorSpecificContentType)
- .getSerializationWriter(vendorSpecificContentType);
+ String cleanedContentType = getVendorSpecificContentType(contentType);
+ SerializationWriterFactory factory = getSerializationWriterFactory(cleanedContentType);
+ if (factory == null) {
+ cleanedContentType = getCleanedVendorSpecificContentType(cleanedContentType);
+ factory =
+ getSerializationWriterFactory(
+ getCleanedVendorSpecificContentType(cleanedContentType));
+ if (factory == null) {
+ throw new RuntimeException(
+ "Content type "
+ + contentType
+ + " does not have a factory to be serialized");
+ }
}
- final String cleanedContentType =
- contentTypeVendorCleanupPattern.matcher(vendorSpecificContentType).replaceAll("");
- if (contentTypeAssociatedFactories.containsKey(cleanedContentType)) {
- return contentTypeAssociatedFactories
- .get(cleanedContentType)
- .getSerializationWriter(cleanedContentType);
+ if (!serializeOnlyChangedValues) {
+ if (factory instanceof BackingStoreSerializationWriterProxyFactory) {
+ return ((BackingStoreSerializationWriterProxyFactory) factory)
+ .getSerializationWriter(cleanedContentType, serializeOnlyChangedValues);
+ }
+ }
+ return factory.getSerializationWriter(cleanedContentType);
+ }
+
+ /**
+ * Gets a SerializationWriterFactory that is mapped to a cleaned content type string
+ * @param contentType wrapper object carrying initial content type and result of parsing it
+ * @return the serialization writer factory or null if no mapped factory is found
+ */
+ @Nullable private SerializationWriterFactory getSerializationWriterFactory(
+ @Nonnull final String contentType) {
+ if (contentTypeAssociatedFactories.containsKey(contentType)) {
+ return contentTypeAssociatedFactories.get(contentType);
}
- throw new RuntimeException(
- "Content type " + contentType + " does not have a factory to be serialized");
+ return null;
+ }
+
+ /**
+ * Splits content type by ; and returns first segment or original contentType
+ * @param contentType
+ * @return vendor specific content type
+ */
+ @Nonnull private String getVendorSpecificContentType(@Nonnull final String contentType) {
+ String[] split = contentType.split(";");
+ if (split.length >= 1) {
+ return split[0];
+ }
+ return contentType;
+ }
+
+ /**
+ * Does a regex match on the content type replacing special characters
+ * @param contentType
+ * @return cleaned content type
+ */
+ @Nonnull private String getCleanedVendorSpecificContentType(@Nonnull final String contentType) {
+ return contentTypeVendorCleanupPattern.matcher(contentType).replaceAll("");
}
}
diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java
index d45d80f89..fe3d34c99 100644
--- a/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java
+++ b/components/abstractions/src/main/java/com/microsoft/kiota/serialization/SerializationWriterProxyFactory.java
@@ -10,10 +10,10 @@
/** Proxy factory that allows the composition of before and after callbacks on existing factories. */
public abstract class SerializationWriterProxyFactory implements SerializationWriterFactory {
@Nonnull public String getValidContentType() {
- return _concrete.getValidContentType();
+ return proxiedFactory.getValidContentType();
}
- private final SerializationWriterFactory _concrete;
+ protected final SerializationWriterFactory proxiedFactory;
private final Consumer _onBefore;
private final Consumer _onAfter;
private final BiConsumer _onStart;
@@ -30,14 +30,14 @@ public SerializationWriterProxyFactory(
@Nullable final Consumer onBeforeSerialization,
@Nullable final Consumer onAfterSerialization,
@Nullable final BiConsumer onStartObjectSerialization) {
- _concrete = Objects.requireNonNull(concrete);
+ proxiedFactory = Objects.requireNonNull(concrete);
_onBefore = onBeforeSerialization;
_onAfter = onAfterSerialization;
_onStart = onStartObjectSerialization;
}
@Nonnull public SerializationWriter getSerializationWriter(@Nonnull final String contentType) {
- final SerializationWriter writer = _concrete.getSerializationWriter(contentType);
+ final SerializationWriter writer = proxiedFactory.getSerializationWriter(contentType);
final Consumer originalBefore = writer.getOnBeforeObjectSerialization();
final Consumer originalAfter = writer.getOnAfterObjectSerialization();
final BiConsumer originalStart =
diff --git a/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java b/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java
index a4681cb2a..b3d0d1fd1 100644
--- a/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java
+++ b/components/abstractions/src/main/java/com/microsoft/kiota/store/BackingStoreSerializationWriterProxyFactory.java
@@ -1,5 +1,6 @@
package com.microsoft.kiota.store;
+import com.microsoft.kiota.serialization.SerializationWriter;
import com.microsoft.kiota.serialization.SerializationWriterFactory;
import com.microsoft.kiota.serialization.SerializationWriterProxyFactory;
@@ -48,4 +49,21 @@ public BackingStoreSerializationWriterProxyFactory(
}
});
}
+
+ /**
+ * Returns a SerializationWriter that overrides the default serialization of only changed values if serializeOnlyChangedValues="true"
+ * Gets the previously proxied serialization writer without any backing store configuration to prevent overwriting the registry affecting
+ * future serialization requests
+ *
+ * @param contentType HTTP content type header value
+ * @param serializeOnlyChangedValues alter backing store default behavior
+ * @return the SerializationWriter
+ */
+ @Nonnull public SerializationWriter getSerializationWriter(
+ @Nonnull final String contentType, final boolean serializeOnlyChangedValues) {
+ if (!serializeOnlyChangedValues) {
+ return proxiedFactory.getSerializationWriter(contentType);
+ }
+ return getSerializationWriter(contentType);
+ }
}
diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java
index 427605cef..320050a7c 100644
--- a/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java
+++ b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/SerializationHelpersTest.java
@@ -1,6 +1,7 @@
package com.microsoft.kiota.serialization;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
@@ -9,13 +10,16 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.microsoft.kiota.serialization.mocks.TestBackedModelEntity;
import com.microsoft.kiota.serialization.mocks.TestEntity;
+import com.microsoft.kiota.store.BackingStoreSerializationWriterProxyFactory;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
class SerializationHelpersTest {
private static final String _jsonContentType = "application/json";
@@ -91,4 +95,83 @@ void serializesObjectCollection() throws IOException {
assertEquals("[{'id':'123'}]", result);
verify(mockSerializationWriter, times(1)).writeCollectionOfObjectValues(eq(""), any());
}
+
+ @Test
+ void serializesAllValuesInBackedModel() throws IOException {
+ final BackingStoreSerializationWriterProxyFactory
+ backingStoreSerializationWriterProxyFactory =
+ new BackingStoreSerializationWriterProxyFactory(
+ new JsonSerializationWriterFactory());
+ SerializationWriterFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.put(
+ _jsonContentType, backingStoreSerializationWriterProxyFactory);
+
+ final TestBackedModelEntity entity = new TestBackedModelEntity();
+ entity.setId("123");
+ entity.setOfficeLocation("Nairobi");
+
+ // Sets the backing store to be initialized. No properties are dirty
+ entity.getBackingStore().setIsInitializationCompleted(true);
+
+ final String result = KiotaJsonSerialization.serializeAsString(entity, false);
+
+ assertFalse(entity.getBackingStore().getReturnOnlyChangedValues());
+ assertEquals("{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}", result);
+
+ final String collectionResult =
+ KiotaJsonSerialization.serializeAsString(
+ new ArrayList<>(Arrays.asList(entity)), false);
+
+ assertEquals("[{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}]", collectionResult);
+ }
+
+ @Test
+ void serializesChangedValuesInBackedModel() throws IOException {
+ final BackingStoreSerializationWriterProxyFactory
+ backingStoreSerializationWriterProxyFactory =
+ new BackingStoreSerializationWriterProxyFactory(
+ new JsonSerializationWriterFactory());
+ SerializationWriterFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.put(
+ _jsonContentType, backingStoreSerializationWriterProxyFactory);
+
+ final TestBackedModelEntity entity = new TestBackedModelEntity();
+ entity.setId("123");
+ entity.setOfficeLocation("Nairobi");
+ entity.getBackingStore().setIsInitializationCompleted(true);
+
+ final String result = KiotaJsonSerialization.serializeAsString(entity, true);
+
+ assertFalse(entity.getBackingStore().getReturnOnlyChangedValues());
+ assertEquals("{}", result);
+
+ final String collectionResult =
+ KiotaJsonSerialization.serializeAsString(
+ new ArrayList<>(Arrays.asList(entity)), true);
+ assertEquals("[{}]", collectionResult);
+ }
+
+ @Test
+ void cleansContentType() throws IOException {
+ final BackingStoreSerializationWriterProxyFactory
+ backingStoreSerializationWriterProxyFactory =
+ new BackingStoreSerializationWriterProxyFactory(
+ new JsonSerializationWriterFactory());
+ SerializationWriterFactoryRegistry.defaultInstance.contentTypeAssociatedFactories.put(
+ _jsonContentType, backingStoreSerializationWriterProxyFactory);
+
+ final TestBackedModelEntity entity = new TestBackedModelEntity();
+ entity.setId("123");
+ entity.setOfficeLocation("Nairobi");
+
+ final String result =
+ KiotaSerialization.serializeAsString(
+ "application/json;odata.metadata=minimal", entity);
+ assertEquals("{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}", result);
+
+ // Because onAfterObjectSerialization, returnOnlyChangedValues is set to false &
+ // initialization is completed
+ entity.getBackingStore().setIsInitializationCompleted(false);
+ final String otherResult =
+ KiotaSerialization.serializeAsString("application/vnd.github.raw+json", entity);
+ assertEquals("{\"id\":\"123\",\"officeLocation\":\"Nairobi\"}", otherResult);
+ }
}
diff --git a/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestBackedModelEntity.java b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestBackedModelEntity.java
new file mode 100644
index 000000000..cadacf5b0
--- /dev/null
+++ b/components/abstractions/src/test/java/com/microsoft/kiota/serialization/mocks/TestBackedModelEntity.java
@@ -0,0 +1,168 @@
+package com.microsoft.kiota.serialization.mocks;
+
+import com.microsoft.kiota.PeriodAndDuration;
+import com.microsoft.kiota.serialization.AdditionalDataHolder;
+import com.microsoft.kiota.serialization.Parsable;
+import com.microsoft.kiota.serialization.ParseNode;
+import com.microsoft.kiota.serialization.SerializationWriter;
+import com.microsoft.kiota.store.BackedModel;
+import com.microsoft.kiota.store.BackingStore;
+import com.microsoft.kiota.store.BackingStoreFactorySingleton;
+
+import jakarta.annotation.Nonnull;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+public class TestBackedModelEntity implements Parsable, AdditionalDataHolder, BackedModel {
+ private BackingStore backingStore;
+
+ public TestBackedModelEntity() {
+ backingStore = BackingStoreFactorySingleton.instance.createBackingStore();
+ }
+
+ public String getId() {
+ return this.backingStore.get("id");
+ }
+
+ public void setId(String id) {
+ this.backingStore.set("id", id);
+ }
+
+ public String getOfficeLocation() {
+ return this.backingStore.get("officeLocation");
+ }
+
+ public void setOfficeLocation(String officeLocation) {
+ this.backingStore.set("officeLocation", officeLocation);
+ }
+
+ public LocalDate getBirthDay() {
+ return this.backingStore.get("birthDay");
+ }
+
+ public void setBirthDay(LocalDate value) {
+ this.backingStore.set("birthDay", value);
+ }
+
+ public PeriodAndDuration getWorkDuration() {
+ return this.backingStore.get("workDuration");
+ }
+
+ public void setWorkDuration(PeriodAndDuration value) {
+ this.backingStore.set("workDuration", PeriodAndDuration.ofPeriodAndDuration(value));
+ }
+
+ public LocalTime getStartWorkTime() {
+ return this.backingStore.get("startWorkTime");
+ }
+
+ public void setStartWorkTime(LocalTime value) {
+ this.backingStore.set("startWorkTime", value);
+ }
+
+ public LocalTime getEndWorkTime() {
+ return this.backingStore.get("endWorkTime");
+ }
+
+ public void setEndWorkTime(LocalTime value) {
+ this.backingStore.set("endWorkTime", value);
+ }
+
+ public OffsetDateTime getCreatedDateTime() {
+ return this.backingStore.get("createdDateTime");
+ }
+
+ public void setCreatedDateTime(OffsetDateTime value) {
+ this.backingStore.set("createdDateTime", value);
+ }
+
+ @Nonnull @Override
+ public Map> getFieldDeserializers() {
+ return new HashMap<>() {
+ {
+ put(
+ "id",
+ n -> {
+ setId(n.getStringValue());
+ });
+ put(
+ "officeLocation",
+ n -> {
+ setOfficeLocation(n.getStringValue());
+ });
+ put(
+ "birthDay",
+ n -> {
+ setBirthDay(n.getLocalDateValue());
+ });
+ put(
+ "workDuration",
+ n -> {
+ setWorkDuration(n.getPeriodAndDurationValue());
+ });
+ put(
+ "startWorkTime",
+ n -> {
+ setStartWorkTime(n.getLocalTimeValue());
+ });
+ put(
+ "endWorkTime",
+ n -> {
+ setEndWorkTime(n.getLocalTimeValue());
+ });
+ put(
+ "createdDateTime",
+ n -> {
+ setCreatedDateTime(n.getOffsetDateTimeValue());
+ });
+ }
+ };
+ }
+
+ @Override
+ public void serialize(@Nonnull SerializationWriter writer) {
+ Objects.requireNonNull(writer);
+ writer.writeStringValue("id", getId());
+ writer.writeStringValue("officeLocation", getOfficeLocation());
+ writer.writeLocalDateValue("birthDay", getBirthDay());
+ writer.writePeriodAndDurationValue("workDuration", getWorkDuration());
+ writer.writeLocalTimeValue("startWorkTime", getStartWorkTime());
+ writer.writeLocalTimeValue("endWorkTime", getEndWorkTime());
+ writer.writeOffsetDateTimeValue("createdDateTime", getCreatedDateTime());
+ writer.writeAdditionalData(getAdditionalData());
+ }
+
+ @Nonnull @Override
+ public Map getAdditionalData() {
+ Map value = this.backingStore.get("additionalData");
+ if (value == null) {
+ value = new HashMap<>();
+ this.setAdditionalData(value);
+ }
+ return value;
+ }
+
+ /**
+ * Sets the AdditionalData property value. Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
+ * @param value Value to set for the AdditionalData property.
+ */
+ public void setAdditionalData(@jakarta.annotation.Nullable final Map value) {
+ this.backingStore.set("additionalData", value);
+ }
+
+ @jakarta.annotation.Nonnull public static TestEntity createFromDiscriminatorValue(
+ @jakarta.annotation.Nonnull final ParseNode parseNode) {
+ return new TestEntity();
+ }
+
+ @Override
+ public BackingStore getBackingStore() {
+ return backingStore;
+ }
+}