Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created separated param serde #311

Merged
merged 14 commits into from
Jan 13, 2025
1 change: 1 addition & 0 deletions examples/gradle-ktor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ repositories {
}

dependencies {
implementation(libs.wirespec.integration)
implementation(libs.bundles.ktor)
implementation(libs.jackson)
implementation(libs.logback)
Expand Down
1 change: 1 addition & 0 deletions examples/gradle-ktor/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ktor_test_server_tests_jvm = { module = "io.ktor:ktor-server-tests-jvm", version
jackson = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
wirespec_compiler = { module = "community.flock.wirespec.compiler:core-jvm", version.ref = "default" }
wirespec_integration = { module = "community.flock.wirespec.integration:wirespec-jvm", version.ref = "default" }

[bundles]
ktor = ["ktor_server_core", "ktor_server_netty", "ktor_server_content_negotiation", "ktor_client", "ktor_serialization_kotlinx_json"]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package community.flock.wirespec.example.maven.custom.app.common

import community.flock.wirespec.kotlin.Wirespec
import community.flock.wirespec.kotlin.serde.DefaultParamSerialization
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.request
Expand All @@ -22,7 +23,7 @@ class WirespecClient(private val httpClient: HttpClient = HttpClient()) {
path(*request.path.toTypedArray())
}
headers {
request.headers.forEach { (t, u) -> appendAll(t, listOf(u)) }
request.headers.forEach { (name, values) -> appendAll(name, values) }
}
}
response.run {
Expand All @@ -35,8 +36,15 @@ class WirespecClient(private val httpClient: HttpClient = HttpClient()) {
}
}

/**
* Example implementation of Wirespec Serialization using DefaultParamSerialization
* This class handles standard parameter serialization for headers and query parameters.
* For custom serialization requirements, you can create your own implementation
* of Wirespec.ParamSerialization instead of using DefaultParamSerialization.
* In this case, you don't need the dependency on community.flock.wirespec.integration:wirespec
*/
@Suppress("UNCHECKED_CAST")
object Serialization : Wirespec.Serialization<String> {
object Serialization : Wirespec.Serialization<String>, Wirespec.ParamSerialization by DefaultParamSerialization() {
override fun <T> serialize(t: T, kType: KType): String =
Json.encodeToString(Json.serializersModule.serializer(kType), t)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ suspend fun ApplicationCall.toRawRequest() =
Wirespec.RawRequest(
method = request.httpMethod.value,
path = request.path().split("/").filter { it.isNotBlank() },
queries = request.queryParameters.toMap().toSingleValueMap(),
headers = request.headers.toMap().toSingleValueMap(),
queries = request.queryParameters.toMap(),
headers = request.headers.toMap(),
body = receive<String>(),
)

Expand Down
6 changes: 5 additions & 1 deletion examples/maven-spring-compile/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>community.flock.wirespec.integration</groupId>
<artifactId>wirespec-jvm</artifactId>
<version>0.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import community.flock.wirespec.example.maven.custom.app.exception.SerializationException;
import community.flock.wirespec.java.Wirespec;
import community.flock.wirespec.java.serde.DefaultParamSerialization;
import org.springframework.stereotype.Component;

import java.lang.reflect.Type;

/**
* Example implementation of Wirespec Serialization using DefaultParamSerialization
* This class handles standard parameter serialization for headers and query parameters.
* For custom serialization requirements, you can create your own implementation
* of Wirespec.ParamSerialization instead of using DefaultParamSerialization.
* In this case, you don't need the dependency on community.flock.wirespec.integration:wirespec
*/
@Component
public class WirespecSerializer implements Wirespec.Serialization<String> {
public class WirespecSerializer implements Wirespec.Serialization<String>, DefaultParamSerialization {

private final ObjectMapper objectMapper;

Expand All @@ -18,20 +25,30 @@ public WirespecSerializer(ObjectMapper objectMapper) {
}

@Override
public <T> String serialize(T t, Type type) {
public <T> String serialize(T body, Type type) {
try {
return objectMapper.writeValueAsString(t);
if (body instanceof String) {
return (String) body;
}
return objectMapper.writeValueAsString(body);
} catch (JsonProcessingException e) {
throw new SerializationException(e);
}
}

@Override
public <T> T deserialize(String s, Type type) {
@SuppressWarnings("unchecked")
public <T> T deserialize(String raw, Type valueType) {
if (raw == null) {
return null;
}
try {
return objectMapper.readValue(s, objectMapper.constructType(type));
if (valueType == String.class) {
return (T) raw;
}
return objectMapper.readValue(raw, objectMapper.constructType(valueType));
} catch (JsonProcessingException e) {
throw new SerializationException(e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import community.flock.wirespec.java.Wirespec.RawRequest;
import community.flock.wirespec.java.Wirespec.RawResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.RequestEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
Expand All @@ -26,17 +27,14 @@ public WirespecTransporter(RestTemplate restTemplate) {
}

public CompletableFuture<RawResponse> transport(RawRequest request) {
final var headers = request.headers().entrySet()
.stream()
.map(it -> Map.entry(it.getKey(), List.of(it.getValue())))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

final var req = new RequestEntity<>(
request.body(),
toMultiValueMap(headers),
valueOf(request.method()),
create(request.path().stream().reduce((acc, cur) -> acc + "/" + cur).orElse(""))
);
final var headers = new HttpHeaders();
headers.putAll(request.headers());

final var req = RequestEntity
.method(valueOf(request.method()), create(request.path().stream().reduce((acc, cur) -> acc + "/" + cur).orElse("")))
.headers(headers)
.body(request.body());

final var res = restTemplate.exchange(req, String.class);
return completedFuture(new RawResponse(
res.getStatusCode().value(),
Expand Down
5 changes: 5 additions & 0 deletions examples/maven-spring-convert/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-reactor</artifactId>
</dependency>
<dependency>
<groupId>community.flock.wirespec.integration</groupId>
<artifactId>wirespec-jvm</artifactId>
<version>0.0.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
import org.springframework.http.RequestEntity
import org.springframework.stereotype.Component
import org.springframework.util.CollectionUtils.toMultiValueMap
import org.springframework.web.client.RestTemplate
import org.springframework.web.client.exchange

Expand Down Expand Up @@ -36,7 +35,7 @@ class LiveKotlinPetstoreClient(
HttpMethod.valueOf(request.method),
URI("https://6467e16be99f0ba0a819fd68.mockapi.io${request.path}"),
)
.headers(HttpHeaders(toMultiValueMap(request.headers.mapValues { listOf(it.value) })))
.headers(HttpHeaders().apply { putAll(request.headers) })
.body(request.body ?: Unit)
.let { client.exchange<String>(it) }
.run { Wirespec.RawResponse(statusCode = statusCode.value(), headers = headers.toSingleValueMap(), body = body) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,34 @@ package community.flock.wirespec.examples.openapi.app

import com.fasterxml.jackson.databind.ObjectMapper
import community.flock.wirespec.kotlin.Wirespec
import community.flock.wirespec.kotlin.serde.DefaultParamSerialization
import org.springframework.stereotype.Component
import kotlin.reflect.KType
import kotlin.reflect.javaType

/**
* Example implementation of Wirespec Serialization using DefaultParamSerialization
* This class handles standard parameter serialization for headers and query parameters.
* For custom serialization requirements, you can create your own implementation
* of Wirespec.ParamSerialization instead of using DefaultParamSerialization.
* In this case, you don't need the dependency on community.flock.wirespec.integration:wirespec
*/
@Component
@OptIn(ExperimentalStdlibApi::class)
class Serialization(private val objectMapper: ObjectMapper) : Wirespec.Serialization<String> {
class Serialization(private val objectMapper: ObjectMapper) :
Wirespec.Serialization<String> {

private val defaultParamSerialization = DefaultParamSerialization()

override fun <T> serialize(t: T, kType: KType): String = objectMapper.writeValueAsString(t)

override fun <T> deserialize(raw: String, kType: KType): T = objectMapper
.constructType(kType.javaType)
.let { objectMapper.readValue(raw, it) }

override fun <T> serializeParam(value: T, kType: KType): List<String> =
defaultParamSerialization.serializeParam(value, kType)

override fun <T> deserializeParam(values: List<String>, kType: KType): T =
defaultParamSerialization.deserializeParam(values, kType)
}
Loading
Loading