Skip to content

Commit

Permalink
add serialization optimization for primitive collection types
Browse files Browse the repository at this point in the history
  • Loading branch information
bmarcaur committed Nov 8, 2024
1 parent e7a024c commit b6196ea
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 0 deletions.
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-2386.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: '[FR] Add Serialization Optimization for Primitive Collection Types'
links:
- https://github.com/palantir/conjure-java/pull/2386
1 change: 1 addition & 0 deletions conjure-lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
implementation 'com.palantir.safe-logging:safe-logging'

testImplementation 'com.palantir.safe-logging:preconditions-assertj'
testImplementation 'com.palantir.conjure.java.runtime:conjure-java-jackson-serialization'
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

package com.palantir.conjure.java.lib.internal;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.IOException;
import java.util.AbstractList;
import java.util.Collection;
import java.util.RandomAccess;
Expand All @@ -26,6 +31,7 @@
* ConjureDoubleList is a boxed list wrapper for the eclipse-collections DoubleArrayList. In eclipse-collections 12,
* a BoxedMutableDoubleList will be released. Once available, ConjureDoubleList should be replaced with that.
*/
@JsonSerialize(using = ConjureDoubleList.Serializer.class)
final class ConjureDoubleList extends AbstractList<Double> implements RandomAccess {
private final DoubleArrayList delegate;

Expand Down Expand Up @@ -69,4 +75,13 @@ public void clear() {
public Double set(int index, Double element) {
return delegate.set(index, element);
}

static final class Serializer extends JsonSerializer<ConjureDoubleList> {
@Override
public void serialize(ConjureDoubleList val, JsonGenerator gen, SerializerProvider _serializer)
throws IOException {
double[] doubles = val.delegate.toArray();
gen.writeArray(doubles, 0, doubles.length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

package com.palantir.conjure.java.lib.internal;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.IOException;
import java.util.AbstractList;
import java.util.Collection;
import java.util.RandomAccess;
Expand All @@ -26,6 +31,7 @@
* ConjureIntegerList is a boxed list wrapper for the eclipse-collections IntArrayList. In eclipse-collections 12,
* a BoxedMutableIntList will be released. Once available, ConjureIntegerList should be replaced with that.
*/
@JsonSerialize(using = ConjureIntegerList.Serializer.class)
final class ConjureIntegerList extends AbstractList<Integer> implements RandomAccess {
private final IntArrayList delegate;

Expand Down Expand Up @@ -69,4 +75,13 @@ public void clear() {
public Integer set(int index, Integer element) {
return delegate.set(index, element);
}

static final class Serializer extends JsonSerializer<ConjureIntegerList> {
@Override
public void serialize(ConjureIntegerList val, JsonGenerator gen, SerializerProvider _serializer)
throws IOException {
int[] integers = val.delegate.toArray();
gen.writeArray(integers, 0, integers.length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@

package com.palantir.conjure.java.lib.internal;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.palantir.conjure.java.lib.SafeLong;
import java.io.IOException;
import java.util.AbstractList;
import java.util.Collection;
import java.util.RandomAccess;
Expand All @@ -27,6 +32,7 @@
* ConjureSafeLongList is a boxed list wrapper for the eclipse-collections LongArrayList. This handles boxing/unboxing
* with SafeLongs.
*/
@JsonSerialize(using = ConjureSafeLongList.Serializer.class)
final class ConjureSafeLongList extends AbstractList<SafeLong> implements RandomAccess {
private final LongArrayList delegate;

Expand Down Expand Up @@ -70,4 +76,15 @@ public void clear() {
public SafeLong set(int index, SafeLong element) {
return SafeLong.of(delegate.set(index, element.longValue()));
}

static final class Serializer extends JsonSerializer<ConjureSafeLongList> {
@Override
public void serialize(ConjureSafeLongList val, JsonGenerator gen, SerializerProvider _serializer)
throws IOException {
// This is safe to serialize without checking because ConjureSafeLongList
// can only store SafeLong's
long[] longs = val.delegate.toArray();
gen.writeArray(longs, 0, longs.length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@

import static org.assertj.core.api.Assertions.assertThat;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.palantir.conjure.java.lib.SafeLong;
import com.palantir.conjure.java.serialization.ObjectMappers;
import java.util.Collection;
import java.util.List;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -82,4 +86,20 @@ public void newNonNullSafeLongList() {
safeLongList.clear();
assertThat(safeLongList).hasSize(0);
}

@Test
public void testSerializationRoundtrip() throws JsonProcessingException {
List<Double> expectedDoubles = List.of(1.1, 2.2, 3.3);
testSerialization(ConjureCollections.newNonNullDoubleList(expectedDoubles), expectedDoubles);
List<Integer> expectedIntegers = List.of(1, 2, 3);
testSerialization(ConjureCollections.newNonNullIntegerList(expectedIntegers), expectedIntegers);
List<SafeLong> expectedSafeLongs = List.of(SafeLong.of(1L), SafeLong.of(2L), SafeLong.of(3L));
testSerialization(ConjureCollections.newNonNullSafeLongList(expectedSafeLongs), expectedSafeLongs);
}

private static final ObjectMapper serverMapper = ObjectMappers.newServerJsonMapper();

private static void testSerialization(Collection<?> actual, Collection<?> expected) throws JsonProcessingException {
assertThat(serverMapper.writeValueAsString(actual)).isEqualTo(serverMapper.writeValueAsString(expected));
}
}

0 comments on commit b6196ea

Please sign in to comment.