Skip to content

Commit

Permalink
Polishing
Browse files Browse the repository at this point in the history
  • Loading branch information
sdeleuze committed Jan 24, 2024
1 parent 11898da commit 4f16297
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,7 +16,8 @@

package org.springframework.http.codec;

import java.util.*;
import java.util.List;
import java.util.Map;

import kotlinx.serialization.KSerializer;
import kotlinx.serialization.StringFormat;
Expand Down Expand Up @@ -92,8 +93,7 @@ public List<MimeType> getDecodableMimeTypes(ResolvableType targetType) {

@Override
public Flux<Object> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
@Nullable MimeType mimeType,
@Nullable Map<String, Object> hints) {
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
return Flux.defer(() -> {
KSerializer<Object> serializer = serializer(elementType);
if (serializer == null) {
Expand All @@ -107,7 +107,7 @@ public Flux<Object> decode(Publisher<DataBuffer> inputStream, ResolvableType ele

@Override
public Mono<Object> decodeToMono(Publisher<DataBuffer> inputStream, ResolvableType elementType,
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
return Mono.defer(() -> {
KSerializer<Object> serializer = serializer(elementType);
if (serializer == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,13 +16,16 @@

package org.springframework.http.codec;

import java.util.*;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import kotlin.text.Charsets;
import kotlinx.serialization.KSerializer;
import kotlinx.serialization.StringFormat;
import org.reactivestreams.Publisher;
import org.springframework.http.MediaType;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand All @@ -32,6 +35,7 @@
import org.springframework.core.codec.EncodingException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.lang.Nullable;
import org.springframework.util.MimeType;

Expand Down Expand Up @@ -87,9 +91,10 @@ public Flux<DataBuffer> encode(Publisher<?> inputStream, DataBufferFactory buffe
.flux();
}

if (mimeType != null && streamingMediaTypes.contains(mimeType)) {
if (mimeType != null && this.streamingMediaTypes.contains(mimeType)) {
return Flux.from(inputStream)
.map(list -> encodeValue(list, bufferFactory, elementType, mimeType, hints).write("\n", Charsets.UTF_8));
.map(list -> encodeValue(list, bufferFactory, elementType, mimeType, hints)
.write("\n", Charsets.UTF_8));
}

ResolvableType listType = ResolvableType.forClassWithGenerics(List.class, elementType);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,21 +16,21 @@

package org.springframework.http.codec.json;

import java.util.List;

import kotlinx.serialization.json.Json;

import org.springframework.http.MediaType;
import org.springframework.http.codec.KotlinSerializationStringEncoder;

import java.util.List;

/**
* Encode from an {@code Object} stream to a byte stream of JSON objects using
* <a href="https://github.com/Kotlin/kotlinx.serialization">kotlinx.serialization</a>.
*
* <p>This encoder can be used to bind {@code @Serializable} Kotlin classes,
* <a href="https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/polymorphism.md#open-polymorphism">open polymorphic serialization</a>
* is not supported.
* It supports {@code application/json} and {@code application/*+json} with
* It supports {@code application/json}, {@code application/x-ndjson} and {@code application/*+json} with
* various character sets, {@code UTF-8} being the default.
*
* @author Sebastien Deleuze
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -69,23 +69,44 @@ class KotlinSerializationJsonDecoderTests : AbstractDecoderTests<KotlinSerializa

@Test
override fun decode() {
val output = decoder.decode(Mono.empty(), ResolvableType.forClass(Pojo::class.java), null, emptyMap())
StepVerifier
.create(output)
.expectError(UnsupportedOperationException::class.java)
val input = Flux.concat(
stringBuffer("{\"bar\":\"b1\",\"foo\":\"f1\"}\n"),
stringBuffer("{\"bar\":\"b2\",\"foo\":\"f2\"}\n")
)

testDecodeAll(input, ResolvableType.forClass(Pojo::class.java), {
it.expectNext(Pojo("f1", "b1"))
.expectNext(Pojo("f2", "b2"))
.expectComplete()
.verify()
}, null, null)
}

@Test
fun decodeStreamWithSingleBuffer() {
val input = Flux.concat(
stringBuffer("{\"bar\":\"b1\",\"foo\":\"f1\"}\n{\"bar\":\"b2\",\"foo\":\"f2\"}\n"),
)

testDecodeAll(input, ResolvableType.forClass(Pojo::class.java), {
it.expectNext(Pojo("f1", "b1"))
.expectNext(Pojo("f2", "b2"))
.expectComplete()
.verify()
}, null, null)
}

@Test
fun decodeStream() {
fun decodeStreamWithMultipleBuffersPerElement() {
val input = Flux.concat(
stringBuffer("{\"bar\":\"b1\",\"foo\":\"f1\"}\n"),
stringBuffer("{\"bar\":\"b2\",\"foo\":\"f2\"}\n")
stringBuffer("{\"bar\":\"b1\","),
stringBuffer("\"foo\":\"f1\"}\n"),
stringBuffer("{\""),
stringBuffer("bar\":\"b2\",\"foo\":\"f2\"}\n")
)

testDecodeAll(input, ResolvableType.forClass(Pojo::class.java), { step: FirstStep<Any> ->
step
.expectNext(Pojo("f1", "b1"))
testDecodeAll(input, ResolvableType.forClass(Pojo::class.java), {
it.expectNext(Pojo("f1", "b1"))
.expectNext(Pojo("f2", "b2"))
.expectComplete()
.verify()
Expand All @@ -100,11 +121,10 @@ class KotlinSerializationJsonDecoderTests : AbstractDecoderTests<KotlinSerializa

val elementType = ResolvableType.forClassWithGenerics(List::class.java, Pojo::class.java)

testDecodeToMonoAll(input, elementType, { step: FirstStep<Any> ->
step
.expectNext(listOf(Pojo("f1", "b1"), Pojo("f2", "b2")))
.expectComplete()
.verify()
testDecodeToMonoAll(input, elementType, {
it.expectNext(listOf(Pojo("f1", "b1"), Pojo("f2", "b2")))
.expectComplete()
.verify()
}, null, null)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -69,30 +69,30 @@ class KotlinSerializationJsonEncoderTests : AbstractEncoderTests<KotlinSerializa
Pojo("foofoo", "barbar"),
Pojo("foofoofoo", "barbarbar")
)
testEncode(input, Pojo::class.java, { step: FirstStep<DataBuffer?> -> step
.consumeNextWith(expectString("[" +
"{\"foo\":\"foo\",\"bar\":\"bar\"}," +
"{\"foo\":\"foofoo\",\"bar\":\"barbar\"}," +
"{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}]")
.andThen { dataBuffer: DataBuffer? -> DataBufferUtils.release(dataBuffer) })
.verifyComplete()
})
testEncode(input, Pojo::class.java) {
it.consumeNextWith(expectString("[" +
"{\"foo\":\"foo\",\"bar\":\"bar\"}," +
"{\"foo\":\"foofoo\",\"bar\":\"barbar\"}," +
"{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}]")
.andThen { dataBuffer -> DataBufferUtils.release(dataBuffer) })
.verifyComplete()
}
}

@Test
fun encodeStream() {
val input = Flux.just(
Pojo("foo", "bar"),
Pojo("foofoo", "barbar"),
Pojo("foofoofoo", "barbarbar")
Pojo("foo", "bar"),
Pojo("foofoo", "barbar"),
Pojo("foofoofoo", "barbarbar")
)
testEncodeAll(
input,
ResolvableType.forClass(Pojo::class.java),
MediaType.APPLICATION_NDJSON,
null
) { step: FirstStep<DataBuffer?> ->
step
.consumeNextWith(expectString("{\"foo\":\"foo\",\"bar\":\"bar\"}\n"))
) {
it.consumeNextWith(expectString("{\"foo\":\"foo\",\"bar\":\"bar\"}\n"))
.consumeNextWith(expectString("{\"foo\":\"foofoo\",\"bar\":\"barbar\"}\n"))
.consumeNextWith(expectString("{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}\n"))
.verifyComplete()
Expand All @@ -102,11 +102,11 @@ class KotlinSerializationJsonEncoderTests : AbstractEncoderTests<KotlinSerializa
@Test
fun encodeMono() {
val input = Mono.just(Pojo("foo", "bar"))
testEncode(input, Pojo::class.java, { step: FirstStep<DataBuffer?> -> step
.consumeNextWith(expectString("{\"foo\":\"foo\",\"bar\":\"bar\"}")
testEncode(input, Pojo::class.java) {
it.consumeNextWith(expectString("{\"foo\":\"foo\",\"bar\":\"bar\"}")
.andThen { dataBuffer: DataBuffer? -> DataBufferUtils.release(dataBuffer) })
.verifyComplete()
})
}
}

@Test
Expand Down

0 comments on commit 4f16297

Please sign in to comment.