Skip to content

Commit c02f307

Browse files
Reintroduce JsonSerdes to reduce breakage
1 parent 5a27fa5 commit c02f307

File tree

1 file changed

+200
-0
lines changed

1 file changed

+200
-0
lines changed
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// Copyright (c) 2023 - Restate Software, Inc., Restate GmbH
2+
//
3+
// This file is part of the Restate Java SDK,
4+
// which is released under the MIT license.
5+
//
6+
// You can find a copy of the license in file LICENSE in the root
7+
// directory of this repository or package, or at
8+
// https://github.com/restatedev/sdk-java/blob/main/LICENSE
9+
package dev.restate.sdk;
10+
11+
import com.fasterxml.jackson.core.JsonFactory;
12+
import com.fasterxml.jackson.core.JsonGenerator;
13+
import com.fasterxml.jackson.core.JsonParser;
14+
import com.fasterxml.jackson.core.JsonToken;
15+
import dev.restate.common.Slice;
16+
import dev.restate.common.function.ThrowingBiConsumer;
17+
import dev.restate.common.function.ThrowingFunction;
18+
import dev.restate.serde.Serde;
19+
import java.io.ByteArrayInputStream;
20+
import java.io.ByteArrayOutputStream;
21+
import java.io.IOException;
22+
import java.util.Map;
23+
import org.jspecify.annotations.NonNull;
24+
25+
/**
26+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
27+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
28+
* ctx.awakeable(Integer.TYPE)}
29+
*/
30+
@Deprecated(since = "2.0", forRemoval = true)
31+
public abstract class JsonSerdes {
32+
33+
private JsonSerdes() {}
34+
35+
/**
36+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
37+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
38+
* ctx.awakeable(Integer.TYPE)}
39+
*/
40+
@Deprecated(since = "2.0", forRemoval = true)
41+
public static final Serde<@NonNull String> STRING =
42+
usingJackson(
43+
"string",
44+
JsonGenerator::writeString,
45+
p -> {
46+
if (p.nextToken() != JsonToken.VALUE_STRING) {
47+
throw new IllegalStateException(
48+
"Expecting token " + JsonToken.VALUE_STRING + ", got " + p.getCurrentToken());
49+
}
50+
return p.getText();
51+
});
52+
53+
/**
54+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
55+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
56+
* ctx.awakeable(Integer.TYPE)}
57+
*/
58+
@Deprecated(since = "2.0", forRemoval = true)
59+
public static final Serde<@NonNull Boolean> BOOLEAN =
60+
usingJackson(
61+
"boolean",
62+
JsonGenerator::writeBoolean,
63+
p -> {
64+
p.nextToken();
65+
return p.getBooleanValue();
66+
});
67+
68+
/**
69+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
70+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
71+
* ctx.awakeable(Integer.TYPE)}
72+
*/
73+
@Deprecated(since = "2.0", forRemoval = true)
74+
public static final Serde<@NonNull Byte> BYTE =
75+
usingJackson(
76+
"number",
77+
JsonGenerator::writeNumber,
78+
p -> {
79+
p.nextToken();
80+
return p.getByteValue();
81+
});
82+
83+
/**
84+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
85+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
86+
* ctx.awakeable(Integer.TYPE)}
87+
*/
88+
@Deprecated(since = "2.0", forRemoval = true)
89+
public static final Serde<@NonNull Short> SHORT =
90+
usingJackson(
91+
"number",
92+
JsonGenerator::writeNumber,
93+
p -> {
94+
p.nextToken();
95+
return p.getShortValue();
96+
});
97+
98+
/**
99+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
100+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
101+
* ctx.awakeable(Integer.TYPE)}
102+
*/
103+
@Deprecated(since = "2.0", forRemoval = true)
104+
public static final Serde<@NonNull Integer> INT =
105+
usingJackson(
106+
"number",
107+
JsonGenerator::writeNumber,
108+
p -> {
109+
p.nextToken();
110+
return p.getIntValue();
111+
});
112+
113+
/**
114+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
115+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
116+
* ctx.awakeable(Integer.TYPE)}
117+
*/
118+
@Deprecated(since = "2.0", forRemoval = true)
119+
public static final Serde<@NonNull Long> LONG =
120+
usingJackson(
121+
"number",
122+
JsonGenerator::writeNumber,
123+
p -> {
124+
p.nextToken();
125+
return p.getLongValue();
126+
});
127+
128+
/**
129+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
130+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
131+
* ctx.awakeable(Integer.TYPE)}
132+
*/
133+
@Deprecated(since = "2.0", forRemoval = true)
134+
public static final Serde<@NonNull Float> FLOAT =
135+
usingJackson(
136+
"number",
137+
JsonGenerator::writeNumber,
138+
p -> {
139+
p.nextToken();
140+
return p.getFloatValue();
141+
});
142+
143+
/**
144+
* @deprecated For primitive types, simply use the overloads of the {@link Context} methods
145+
* accepting {@link Class}, for example {@code ctx.run(String.class, myClosure)} or {@code
146+
* ctx.awakeable(Integer.TYPE)}
147+
*/
148+
@Deprecated(since = "2.0", forRemoval = true)
149+
public static final Serde<@NonNull Double> DOUBLE =
150+
usingJackson(
151+
"number",
152+
JsonGenerator::writeNumber,
153+
p -> {
154+
p.nextToken();
155+
return p.getDoubleValue();
156+
});
157+
158+
// --- Helpers for jackson-core
159+
160+
private static final JsonFactory JSON_FACTORY = new JsonFactory();
161+
162+
private static <T extends @NonNull Object> Serde<T> usingJackson(
163+
String type,
164+
ThrowingBiConsumer<JsonGenerator, T> serializer,
165+
ThrowingFunction<JsonParser, T> deserializer) {
166+
return new Serde<>() {
167+
168+
@Override
169+
public Schema jsonSchema() {
170+
return new JsonSchema(Map.of("type", type));
171+
}
172+
173+
@Override
174+
public Slice serialize(T value) {
175+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
176+
try (JsonGenerator gen = JSON_FACTORY.createGenerator(outputStream)) {
177+
serializer.asBiConsumer().accept(gen, value);
178+
} catch (IOException e) {
179+
throw new RuntimeException("Cannot create JsonGenerator", e);
180+
}
181+
return Slice.wrap(outputStream.toByteArray());
182+
}
183+
184+
@Override
185+
public T deserialize(Slice value) {
186+
ByteArrayInputStream inputStream = new ByteArrayInputStream(value.toByteArray());
187+
try (JsonParser parser = JSON_FACTORY.createParser(inputStream)) {
188+
return deserializer.asFunction().apply(parser);
189+
} catch (IOException e) {
190+
throw new RuntimeException("Cannot create JsonGenerator", e);
191+
}
192+
}
193+
194+
@Override
195+
public String contentType() {
196+
return "application/json";
197+
}
198+
};
199+
}
200+
}

0 commit comments

Comments
 (0)