
net.dongliu.xhttp.json.JsonProcessor Maven / Gradle / Ivy
The newest version!
package net.dongliu.xhttp.json;
import net.dongliu.xhttp.*;
import net.dongliu.xhttp.body.AbstractBody;
import net.dongliu.xhttp.body.Body;
import java.io.*;
import java.lang.reflect.Type;
import java.net.http.HttpRequest;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;
/**
* Json processor, used to decode/encode json values, blocking and non-blocking.
*
* @author Liu Dong
*/
public abstract class JsonProcessor {
/**
* Serialize value to json, and write to writer. The output stream is leaved unclosed.
*/
protected abstract void marshal(Object value, OutputStream out, Charset charset) throws IOException;
/**
* Deserialize json from Reader, to specific type. The input stream is closed when finished or error occurred.
*
* @param charset the charset, cannot be null
*/
protected abstract T unmarshal(InputStream in, Charset charset, Type type) throws IOException;
/**
* Create a new json http body
*
* @param value the value of body, to be marshall by this processor
* @param the value type
* @return json http body
*/
public Body jsonBody(T value) {
return new JsonBody<>(value);
}
/**
* Create a new json http body
*
* @param value the value of body, to be marshall by this processor
* @param the value type
* @return json http body
*/
public Body jsonBody(T value, Charset charset) {
return new JsonBody<>(value, charset);
}
/**
* Return a ResponseHandler, which deserialize json with charset and type.
*/
public ResponseHandler responseHandler(Class type) {
return responseHandler((Type) type);
}
/**
* Return a ResponseHandler, which deserialize json with charset and type.
*/
public ResponseHandler responseHandler(TypeToken type) {
return responseHandler(type.getType());
}
/**
* Return a ResponseHandler, which deserialize json with charset and type.
*/
private ResponseHandler responseHandler(Type type) {
return (statusCode, headers, body, charset) -> unmarshal(body, charset.get(), type);
}
/**
* Return a AsyncResponseHandler, which deserialize json from ByteBuffers async, with charset and type.
*/
public AsyncResponseHandler asyncResponseHandler(TypeToken typeToken) {
return asyncResponseHandler(typeToken.getType());
}
/**
* Return a AsyncResponseHandler, which deserialize json from ByteBuffers async, with charset and type.
*/
public AsyncResponseHandler asyncResponseHandler(Class cls) {
return asyncResponseHandler((Type) cls);
}
/**
* Return a AsyncResponseHandler, which deserialize json from ByteBuffers async, with charset and type.
* Default impl read all data of response body unblocking, and then unmarshal using blocking api.
* Override this method if implementation can decode json with non-blocking API.
*/
protected AsyncResponseHandler asyncResponseHandler(Type type) {
requireNonNull(type);
return new JsonBodyHandler<>(type);
}
/**
* Json http body
*
* @param the value type
*/
private class JsonBody extends AbstractBody implements Body {
private JsonBody(T value) {
this(value, UTF_8);
}
private JsonBody(T value, Charset charset) {
super(value, ContentType.of(MimeType.JSON, requireNonNull(charset)));
}
@Override
public HttpRequest.BodyPublisher asBodyPublisher() {
return asPublisher(body(), contentType().charset().orElseThrow());
}
/**
* Marshal value to json, for async http using. Default using block api to get all data once, and then publish.
*
* @param value the value
* @param charset the charset
* @return http body publisher
*/
HttpRequest.BodyPublisher asPublisher(Object value, Charset charset) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
marshal(value, bos, charset);
return HttpRequest.BodyPublishers.ofByteArray(bos.toByteArray());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
private class JsonBodyHandler implements AsyncResponseHandler {
private Charset charset;
private final Type type;
private List buffers;
private JsonBodyHandler(Type type) {
this.type = type;
}
@Override
public void onHeader(int statusCode, Headers headers, Supplier charset) {
this.charset = charset.get();
this.buffers = new ArrayList<>();
}
@Override
public void onBodyChunk(ByteBuffer buffer) {
this.buffers.add(buffer);
}
@Override
public T onBodyEnd() throws Exception {
try (var in = new ByteBuffersInputStream(buffers)) {
return unmarshal(in, charset, type);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy