Closed dakotahNorth closed 7 months ago
Have not used jackson with manifold-json, but the jackson documentation claims if you include the javac -parameters
argument, all the wiring annotations are not required. Have you tried that?
Just. tried that. Changed the build to use -parameters
... same issue.
The issue arises from
Object event = objectMapper.treeToValue(jsonNode, eventClass);
Where ObjectMapper.treeToValue
expects a class with a default constructor and JavaBean methods. The runtime exception above is when treeToValue
tries to instantiate the eventClass
with default constructor.
Jackson also supports using a builder ... but then I would need to annotate the JSON object. Similar to below ...
@JsonDeserialize(builder = ExampleEvent.ExampleEventBuilder.class)
public class ExampleEvent {
private final String data;
private ExampleEvent(String data) {
this.data = data;
}
// Getter
public String getData() {
return data;
}
// Builder
public static class ExampleEventBuilder {
private String data;
public ExampleEventBuilder withData(String data) {
this.data = data;
return this;
}
public ExampleEvent build() {
return new ExampleEvent(data);
}
}
}
Researching Jackson to see if builder pattern can be configured as the default so the annotation isn't needed.
There was no easy way for Jackson to switch over without creating custom bindings.
Instead ported code to FastJSON, which worked really nicely with Manifold.
Good to know re FastJSON. Curious to know why you aren't just using manifold-json, why FastJson at all?
Oh ... right.
I have a general message handler that parses all JSON into a JSONObject and then passes that to the message handler.
void onMessageReceived(String messagePayload) {
try {
JSONObject rootNode = JSON.parseObject(messagePayload);
String messageType = rootNode.getString("messageType");
List<Consumer<JSONObject>> handlers = messageTypeHandlers.get(messageType);
if (handlers != null && !handlers.isEmpty()) {
handlers.forEach(handler -> handler.accept(rootNode));
} else {
System.out.println("Unhandled messageType: " + messageType);
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
And shows up as an ExampleEvent
(from JSON) in MessageHandler
:
@MessageHandler
public final void handleExampleEvent(ExampleEvent event) { receivedEvents.add(event); }
Could I have done that with manifold?
Could I have done that with manifold?
From what I can gather, yes. You can use manifold.json.rt.Json.fromJson(String)
in place of JSON.parseObject(String)
.
void onMessageReceived(String messagePayload) {
try {
Bindings rootNode = (Bindings) Json.fromJson(messagePayload);
String messageType = (String) rootNode.get("messageType");
List<Consumer<Bindings>> handlers = messageTypeHandlers.get(messageType);
if (handlers != null && !handlers.isEmpty()) {
handlers.forEach(handler -> handler.accept(rootNode));
} else {
System.out.println("Unhandled messageType: " + messageType);
}
} catch (RuntimeException e) {
e.printStackTrace();
}
}
Taking it to another level, the message payload could be made type-safe instead of using untyped JsonObject/Bindings. Given messageType
can map to a Java type corresponding with manifold-json, consumers of events could be hardcore type-safe. Think Consumer<T>
as opposed to Consumer<JsonNode>
. But that may not make sense depending on your problem space.
This could be achieved using the Xxx.load().fromJson(jsonString)
where Xxx
is a manifold-json derived type. Since you are loading these dynamically, you would have to use this API reflectively.
String jsonJavaType = (String) rootNode.get("messageType");
Loader<?> loader = (Loader<?>) ReflectUtil.method(jsonJavaType, "load").invokeStatic();
Object typesafeObj = loader.fromJson(rootNode.get("message"));
...
List<Consumer> handlers = messageTypeHandlers.get(messageType);
handlers.forEach(handler -> handler.accept(typesafeObj)); // type-safe at method receiver
Where handler could be something like:
public class MyMessageConsumer implements Consumer<MyMessageType> {
public void accept(MyMessageType t) {
. . .
}
}
Anyhow, food for thought.
That is super helpful ... thank you!
Trying to create an object to use with fasterxml/jackson
This code worked when ExampleEvent was a concrete Java class that is simply a Java object for a JSON class.
And the concrecte Java class
But, this seemed like a perfect example to use manifold JSON schema to define the class.
But when using the Manifold class, the following error occrus.
Should JSON created object have a default constructor?
How to handle the ability for
@JsonIgnoreProperties(ignoreUnknown = true)
?