-
-
Notifications
You must be signed in to change notification settings - Fork 266
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
Add JSON serializability to new specs #1035
Comments
Looking into this after quite a while 😓 . Most specs could have their @JsonSerialize(as = XSpec.class)
@JsonDeserialize(as = XSpec.class) Some considerations must be taken regarding
|
EDIT: Stupid me, I just realized that discord4j's json module already has a custom serializer/deserializer for possibles. I wrote my own for nothing. I was looking at this for a bit I used ObjectMapper to convert between classes and JSON. ObjectMapper is part of json-databind, which is visible to discord4j's json module, but not to the core module that all of the specs are located in right now. Anyways, I ran into, like, two problems:
I did do a bit of modification to a local copy of D4J, doing what @quanticc suggested with the JsonSerialize, JsonDeserialize, and JsonIgnore annotations. So the following code likely would not work with an actual current release of D4J. The generated JSON is insanely long. Probably not practical
And then you can convert it back into the spec
Overall, I ended up with something like this public class Main {
public static void main(String[] args) {
// I just copied this from the D4J docs
MessageCreateSpec spec = MessageCreateSpec.create()
.withContent("Hey")
.withComponents(ActionRow.of(Button.success("hey", "Click me!")));
// The actual interesting part
ObjectMapper objectMapper = JsonMapper.builder()
.disable(MapperFeature.AUTO_DETECT_IS_GETTERS)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.build();
SimpleModule module = new SimpleModule();
module.addSerializer(Possible.class, new PossibleSerializer());
module.addDeserializer(Possible.class, new PossibleDeserializer());
objectMapper.registerModule(module);
String serialized = null;
try {
serialized = objectMapper.writeValueAsString(spec);
System.out.println(serialized);
System.out.println(objectMapper.readValue(serialized, MessageCreateSpec.class));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
} // "Possible" has to be kept as a rawtype. The compiler will complain if you do "Possible<?>"
public class PossibleDeserializer extends JsonDeserializer<Possible> {
@Override
public Possible deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
boolean present = node.get("present").asBoolean();
if (present) {
JsonNode value = node.get("value");
String className = node.get("cls").asText();
try {
Class<?> cls = Class.forName(className);
return Possible.of(jsonParser.getCodec().treeToValue(value, cls));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} else {
return Possible.absent();
}
}
} public class PossibleSerializer extends JsonSerializer<Possible> {
@Override
public void serialize(Possible possible, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeBooleanField("present", !possible.isAbsent());
if (!possible.isAbsent()) {
jsonGenerator.writeObjectField("cls", possible.get().getClass().getName());
jsonGenerator.writeObjectField("value", possible.get());
}
jsonGenerator.writeEndObject();
}
} Right now I just have the code in it's own project because it was easier to test that way. |
Feature Description:
Currently, there is no supported way to serialize the new specs into JSON and deserialize them back from JSON.
Example use case: (Embed pagination)
EmbedCreateSpec
instances and stored in a persistence layer.Justification:
Besides supporting the above use case, Legacy specs already have this functionality and it should be ported over to the new specs.
LegacySpec#asRequest
LegacyXSpec#from(XData)
methods.The new specs could implement this same behavior, or something else entirely. However, it would be nice to add this functionality before Legacy specs are removed.
The text was updated successfully, but these errors were encountered: