Skip to content

Commit

Permalink
Merge pull request #72 from fingerprintjs/do-not-use-nullable
Browse files Browse the repository at this point in the history
[Prerelease] Don't use `jackson-databind-nullable` to fix serialization problems with `Jackson` default configuration
  • Loading branch information
ilfa authored Sep 10, 2024
2 parents 1b7a5ab + 979b800 commit 9c3a482
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 46 deletions.
2 changes: 1 addition & 1 deletion commitlint.config.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = { extends: ['@commitlint/config-conventional'] };
module.exports = { extends: ['@fingerprintjs/commit-lint-dx-team'] };
4 changes: 1 addition & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[versions]
jackson = "2.17.2"
jackson-databind-nullable = "0.2.6"
jakarta-annotation-api = "2.0.0"
jersey = "3.1.7"
junit = "5.10.2"
Expand All @@ -12,7 +11,6 @@ swagger-annotations = "2.2.22"
jackson-annotations = { module = "com.fasterxml.jackson.core:jackson-annotations", version.ref = "jackson" }
jackson-core = { module = "com.fasterxml.jackson.core:jackson-core", version.ref = "jackson" }
jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" }
jackson-databind-nullable = { module = "org.openapitools:jackson-databind-nullable", version.ref = "jackson-databind-nullable" }
jackson-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" }
jakarta-annotation-api = { module = "jakarta.annotation:jakarta.annotation-api", version.ref = "jakarta-annotation-api" }
jersey-apache-connector = { module = "org.glassfish.jersey.connectors:jersey-apache-connector", version.ref = "jersey" }
Expand All @@ -26,4 +24,4 @@ mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" }
swagger-annotations = { module = "io.swagger.core.v3:swagger-annotations", version.ref = "swagger-annotations" }

[plugins]
openapi-generator = { id = "org.openapi.generator", version.ref = "openapi" }
openapi-generator = { id = "org.openapi.generator", version.ref = "openapi" }
4 changes: 2 additions & 2 deletions sdk/sdk.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ dependencies {
api(libs.jackson.core)
api(libs.jackson.annotations)
api(libs.jackson.databind)
api(libs.jackson.databind.nullable)
api(libs.jackson.jsr310)
api(libs.jakarta.annotation.api)
testImplementation(libs.junit.jupiter.api)
Expand Down Expand Up @@ -68,6 +67,7 @@ openApiGenerate {
gitRepoId.set("fingerprint-pro-server-api-java-sdk")
gitUserId.set("fingerprintjs")
configOptions.put("hideGenerationTimestamp", "true")
configOptions.put("openApiNullable", "false")
}

tasks.register("removeDocs") {
Expand Down Expand Up @@ -143,4 +143,4 @@ tasks.test {

tasks.jar {
archiveBaseName = "fingerprint-pro-server-api-sdk"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@
import com.fasterxml.jackson.annotation.JsonValue;
import com.fingerprint.model.Error;
import java.util.Arrays;
import org.openapitools.jackson.nullable.JsonNullable;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.openapitools.jackson.nullable.JsonNullable;
import java.util.NoSuchElementException;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fingerprint.sdk.JSON;
import io.swagger.v3.oas.annotations.media.Schema;
Expand All @@ -32,7 +28,7 @@ public class RawDeviceAttributesResultValue {
private Error error;

public static final String JSON_PROPERTY_VALUE = "value";
private JsonNullable<Object> value = JsonNullable.<Object>of(null);
private Object value = null;

public RawDeviceAttributesResultValue() {
}
Expand Down Expand Up @@ -64,7 +60,7 @@ public void setError(Error error) {


public RawDeviceAttributesResultValue value(Object value) {
this.value = JsonNullable.<Object>of(value);
this.value = value;
return this;
}

Expand All @@ -74,26 +70,18 @@ public RawDeviceAttributesResultValue value(Object value) {
**/
@jakarta.annotation.Nullable
@Schema(description = "")
@JsonIgnore

public Object getValue() {
return value.orElse(null);
}

@JsonProperty(JSON_PROPERTY_VALUE)
@JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)

public JsonNullable<Object> getValue_JsonNullable() {
public Object getValue() {
return value;
}

@JsonProperty(JSON_PROPERTY_VALUE)
public void setValue_JsonNullable(JsonNullable<Object> value) {
this.value = value;
}


@JsonProperty(JSON_PROPERTY_VALUE)
@JsonInclude(value = JsonInclude.Include.USE_DEFAULTS)
public void setValue(Object value) {
this.value = JsonNullable.<Object>of(value);
this.value = value;
}


Expand All @@ -110,23 +98,12 @@ public boolean equals(Object o) {
}
RawDeviceAttributesResultValue rawDeviceAttributesResultValue = (RawDeviceAttributesResultValue) o;
return Objects.equals(this.error, rawDeviceAttributesResultValue.error) &&
equalsNullable(this.value, rawDeviceAttributesResultValue.value);
}

private static <T> boolean equalsNullable(JsonNullable<T> a, JsonNullable<T> b) {
return a == b || (a != null && b != null && a.isPresent() && b.isPresent() && Objects.deepEquals(a.get(), b.get()));
Objects.equals(this.value, rawDeviceAttributesResultValue.value);
}

@Override
public int hashCode() {
return Objects.hash(error, hashCodeNullable(value));
}

private static <T> int hashCodeNullable(JsonNullable<T> a) {
if (a == null) {
return 1;
}
return a.isPresent() ? Arrays.deepHashCode(new Object[]{a.get()}) : 31;
return Objects.hash(error, value);
}

@Override
Expand Down
3 changes: 0 additions & 3 deletions sdk/src/main/java/com/fingerprint/sdk/JSON.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.openapitools.jackson.nullable.JsonNullableModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fingerprint.model.*;

Expand All @@ -30,8 +29,6 @@ public JSON() {
mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
mapper.setDateFormat(new RFC3339DateFormat());
mapper.registerModule(new JavaTimeModule());
JsonNullableModule jnm = new JsonNullableModule();
mapper.registerModule(jnm);
}

/**
Expand Down
56 changes: 56 additions & 0 deletions sdk/src/test/java/com/fingerprint/SerializationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.fingerprint;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fingerprint.model.EventResponse;
import com.fingerprint.model.RawDeviceAttributesResultValue;
import com.fingerprint.model.SignalResponseRawDeviceAttributes;
import com.fingerprint.sdk.ApiException;
import com.fingerprint.sdk.JSON;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import java.io.IOException;
import java.io.InputStream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class SerializationTest {

private InputStream getFileAsIOStream(final String fileName) {
InputStream ioStream = this.getClass()
.getClassLoader()
.getResourceAsStream(fileName);

if (ioStream == null) {
throw new IllegalArgumentException(fileName + " is not found");
}
return ioStream;
}

private static ObjectMapper getMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
return mapper;
}

@Test
public void serializeRawDeviceAttributesTest() throws IOException {
ObjectMapper sdkObjectMapper = JSON.getDefault().getMapper();
EventResponse eventResponse = sdkObjectMapper.readValue(getFileAsIOStream("mocks/get_event_200.json"), EventResponse.class);

SignalResponseRawDeviceAttributes signalResponseRawDeviceAttributes = eventResponse.getProducts().getRawDeviceAttributes();
String sdkResult = sdkObjectMapper.writeValueAsString(signalResponseRawDeviceAttributes);

ObjectMapper springLikeObjectMapper = getMapper();
String springResult = springLikeObjectMapper.writeValueAsString(signalResponseRawDeviceAttributes);

assertTrue(sdkResult.contains("\"architecture\":{\"value\":127}"));
assertTrue(springResult.contains("\"architecture\":{\"error\":null,\"value\":127}"));
}
}
5 changes: 0 additions & 5 deletions sdk/src/test/java/com/fingerprint/api/FingerprintApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import org.junit.jupiter.api.TestInstance;
import org.mockito.Mockito;
import org.openapitools.jackson.nullable.JsonNullableModule;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -69,8 +68,6 @@ private static ObjectMapper getMapper() {
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JsonNullableModule jnm = new JsonNullableModule();
mapper.registerModule(jnm);
return mapper;
}

Expand Down Expand Up @@ -263,8 +260,6 @@ public void getVisitsTest() throws ApiException {
public void webhookTest() throws Exception {
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
JsonNullableModule jnm = new JsonNullableModule();
mapper.registerModule(jnm);

WebhookVisit visit = mapper.readValue(getFileAsIOStream("mocks/webhook.json"), WebhookVisit.class);

Expand Down

0 comments on commit 9c3a482

Please sign in to comment.