Json 用Jackson序列化和反序列化Lambda
我正在尝试序列化和反序列化一个类Json 用Jackson序列化和反序列化Lambda,json,serialization,lambda,java-8,jackson,Json,Serialization,Lambda,Java 8,Jackson,我正在尝试序列化和反序列化一个类RuleMessage,但无法使其工作。这是我的密码: public class RuleMessage { private String id; private SerializableRunnable sRunnable; public RuleMessage(String id, SerializableRunnable sRunnable) { this.id = id; this.sRunnabl
RuleMessage
,但无法使其工作。这是我的密码:
public class RuleMessage {
private String id;
private SerializableRunnable sRunnable;
public RuleMessage(String id, SerializableRunnable sRunnable) {
this.id = id;
this.sRunnable = sRunnable;
}
}
我正在使用
Java8
。有人能告诉我这在Jackson
库中是否可行吗?首先,在RuleMessage中,您必须创建getter/setter或将字段公开,以便提供对字段的Jackson访问
然后,您的代码打印如下内容:
{"@class":"RuleMessage","id":"1","sRunnable":{"@class":"RuleMessage$$Lambda$20/0x0000000800b91c40"}}
new RuleMessage("1", new Runner())
无法反序列化此JSON文档,因为RuleMessage没有默认构造函数,并且无法构造lambda
您可以创建一个类,而不是lambda:
public class Runner implements SerializableRunnable {
@Override
public void run() {
System.out.println("Serializable!");
}
}
然后像这样构造您的pojo:
{"@class":"RuleMessage","id":"1","sRunnable":{"@class":"RuleMessage$$Lambda$20/0x0000000800b91c40"}}
new RuleMessage("1", new Runner())
Jackson反序列化程序现在可以重建对象并执行运行程序。
Jackson
创建的目的是保持对象状态不改变行为。这就是为什么它试图使用getter
、setter
等来序列化POJO
的属性。序列化lambda打破了这个想法。没有任何要序列化的属性,只有一个应该调用的方法。序列化原始lambda对象真的是个坏主意,你们应该重新设计你们的应用程序以避免类似的用例
在您的例子中,SerializableRunnable
接口扩展了java.io.Serializable
,它提供了一个选项-。使用java.io.ObjectOutputStream
我们可以将lambda对象序列化为字节数组,并使用Base64
编码在JSON
有效负载中对其进行序列化Jackson
支持提供writeBinary
和getBinaryValue
方法的此场景
下面是一个简单的示例:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class JsonLambdaApp {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
SerializableRunnable action = () -> System.out.println("Serializable!");
String json = mapper.writeValueAsString(new RuleMessage("1", action));
System.out.println(json);
RuleMessage ruleMessage = mapper.readValue(json, RuleMessage.class);
ruleMessage.getsRunnable().run();
}
}
@JsonSerialize(using = LambdaJsonSerializer.class)
@JsonDeserialize(using = LambdaJsonDeserializer.class)
interface SerializableRunnable extends Runnable, Serializable {
}
class LambdaJsonSerializer extends JsonSerializer<SerializableRunnable> {
@Override
public void serialize(SerializableRunnable value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream)) {
outputStream.writeObject(value);
gen.writeBinary(byteArrayOutputStream.toByteArray());
}
}
}
class LambdaJsonDeserializer extends JsonDeserializer<SerializableRunnable> {
@Override
public SerializableRunnable deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
byte[] value = p.getBinaryValue();
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(value);
ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream)) {
return (SerializableRunnable) inputStream.readObject();
} catch (ClassNotFoundException e) {
throw new IOException(e);
}
}
}
class RuleMessage {
private String id;
private SerializableRunnable sRunnable;
@JsonCreator
public RuleMessage(@JsonProperty("id") String id, @JsonProperty("sRunnable") SerializableRunnable sRunnable) {
this.id = id;
this.sRunnable = sRunnable;
}
public String getId() {
return id;
}
public SerializableRunnable getsRunnable() {
return sRunnable;
}
}
和lambda:
Serializable!
另见:
Serializable!