Skip to content

Commit

Permalink
Add io-jackson
Browse files Browse the repository at this point in the history
  • Loading branch information
AterAnimAvis committed Apr 11, 2024
1 parent 3c744fc commit be43dbf
Show file tree
Hide file tree
Showing 53 changed files with 2,109 additions and 2 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ There are five subprojects within the repository:
- **`core`** - the main data interfaces and implementations (immutables and builders).
- **`io-gson`** - JSON adapters for the [Gson](https://github.com/google/gson) library
- **`io-moshi`** - JSON adapters for the [Moshi](https://github.com/square/moshi) library.
- **`io-jackson`** - JSON adapters for the [Jackson](https://github.com/FasterXML/jackson-core) library.
- **`io-proguard`** - parsing for ProGuard mapping files
- **`utils`** - miscellaneous utilities not fit for inclusion in the core library

Expand All @@ -31,14 +32,15 @@ dependencies {
implementation "org.parchmentmc:feather:${feather_version}"
implementation "org.parchmentmc.feather:io-gson:${feather_version}" // For the Gson adapters
implementation "org.parchmentmc.feather:io-moshi:${feather_version}" // For the Moshi adapters
implementation "org.parchmentmc.feather:io-jackson:${feather_version}" // For the Jackson adapters
implementation "org.parchmentmc.feather:io-proguard:${feather_version}" // For the ProGuard parser
implementation "org.parchmentmc.feather:utils:${feather_version}" // For the misc. utilities
}
```

### The IO Libraries

Feather offers JSON adapters for two JSON parsing libraries: Gson and Moshi.
Feather offers JSON adapters for three JSON parsing libraries: Gson, Moshi and Jackson.

```java
class UsingGson {
Expand Down Expand Up @@ -68,6 +70,20 @@ class UsingMoshi {
.add(new OffsetDateTimeAdapter())
.create();
}

class UsingJackson {
final ObjectMapper jackson = new ObjectMapper()
// Required for `MappingDataContainer` and inner data classes
.registerModule(new MDCModule()) // Automatically adds `SimpleVersionModule`
// Required for `MappingDataContainer`s and `SourceMetadata`
.registerModule(new SimpleVersionModule())
// Required for the metadata classes (`SourceMetadata`, `MethodReference`, etc.) and `Named`
.registerModule(new MetadataModule()) // Automatically adds `SimpleVersionModule`
// Required for parsing manifests: `LauncherManifest`, `VersionManifest`, and their inner data classes
.registerModule(new OffsetDateTimeModule())
// Alternatively every Module combined.
.registerModule(new FeatherModule()); // Automatically adds `MDCModule`, `SimpleVersionModule`, `MetadataModule` and `OffsetDateTimeModule`
}
```

## License
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ guava = '32.0.1-jre'

# IO subproject dependencies
gson = '2.10.1'
jackson = '2.16.0'
moshi = '1.12.0' # Fixed to 1.12.0 because that's the last version written in Java

# Test engine
Expand All @@ -15,6 +16,7 @@ checker-qual = { module = 'org.checkerframework:checker-qual', version.ref = 'ch
guava = { module = 'com.google.guava:guava', version.ref = 'guava' }

gson = { module = 'com.google.code.gson:gson', version.ref = 'gson' }
jackson = { module = 'com.fasterxml.jackson.core:jackson-databind', version.ref = 'jackson' }
moshi = { module = 'com.squareup.moshi:moshi', version.ref = 'moshi' }

junit-api = { module = 'org.junit.jupiter:junit-jupiter-api', version.ref = 'junit' }
Expand Down
19 changes: 19 additions & 0 deletions io-jackson/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
group = 'org.parchmentmc.feather'
archivesBaseName = 'io-jackson'

dependencies {
api project(':feather')
api libs.jackson

testFixturesApi testFixtures(project(':feather'))
}

publishing {
publications.create("jacksonIO", MavenPublication) {
from components.java
pom {
name = "Feather IO - Jackson"
description = "Additional IO library for serializing JSON data objects using Jackson."
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.parchmentmc.feather.io.jackson;

import com.fasterxml.jackson.core.Version;
import org.parchmentmc.feather.io.jackson.modules.MDCModule;
import org.parchmentmc.feather.io.jackson.modules.MetadataModule;
import org.parchmentmc.feather.io.jackson.modules.OffsetDateTimeModule;
import org.parchmentmc.feather.io.jackson.modules.SimpleVersionModule;
import org.parchmentmc.feather.io.jackson.util.BaseModule;

import java.time.format.DateTimeFormatter;

public class FeatherModule extends BaseModule {

// TODO: Base it on Implementation-Version? We should probably be adding that in the META-INF
public static final Version VERSION = Version.unknownVersion();

public FeatherModule() {
this(false, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}

/**
* @param ignoreNonDocumented whether this should ignore mapping data entries which have no javadocs.
* @param formatter formatter used to serialize and deserialize OffsetDateTime.
*/
public FeatherModule(boolean ignoreNonDocumented, DateTimeFormatter formatter) {
super("FeatherModule", FeatherModule.VERSION);
addDependency(new MDCModule(ignoreNonDocumented));
addDependency(new MetadataModule());
addDependency(new OffsetDateTimeModule(formatter));
addDependency(new SimpleVersionModule());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.parchmentmc.feather.io.jackson.modules;

import org.parchmentmc.feather.io.jackson.FeatherModule;
import org.parchmentmc.feather.io.jackson.modules.mdc.*;
import org.parchmentmc.feather.io.jackson.util.BaseModule;
import org.parchmentmc.feather.mapping.MappingDataContainer;
import org.parchmentmc.feather.mapping.VersionedMappingDataContainer;

public class MDCModule extends BaseModule {

private final boolean ignoreNonDocumented;

public MDCModule() {
this(false);
}

/**
* @param ignoreNonDocumented whether this should ignore mapping data entries which have no javadocs.
*/
public MDCModule(boolean ignoreNonDocumented) {
super("Feather$MDC", FeatherModule.VERSION);
addDependency(new SimpleVersionModule());

addSerializer(VersionedMappingDataContainer.class, new VersionedMappingDataContainerSerializer());
addDeserializer(VersionedMappingDataContainer.class, new VersionedMappingDataContainerDeserializer());
addSerializer(MappingDataContainer.PackageData.class, new PackageDataSerializer());
addDeserializer(MappingDataContainer.PackageData.class, new PackageDataDeserializer());
addSerializer(MappingDataContainer.ClassData.class, new ClassDataSerializer(ignoreNonDocumented));
addDeserializer(MappingDataContainer.ClassData.class, new ClassDataDeserializer());
addSerializer(MappingDataContainer.FieldData.class, new FieldDataSerializer(ignoreNonDocumented));
addDeserializer(MappingDataContainer.FieldData.class, new FieldDataDeserializer());
addSerializer(MappingDataContainer.MethodData.class, new MethodDataSerializer(ignoreNonDocumented));
addDeserializer(MappingDataContainer.MethodData.class, new MethodDataDeserializer());
addSerializer(MappingDataContainer.ParameterData.class, new ParameterDataSerializer(ignoreNonDocumented));
addDeserializer(MappingDataContainer.ParameterData.class, new ParameterDataDeserializer());

this.ignoreNonDocumented = ignoreNonDocumented;
}

public boolean isIgnoreNonDocumented() {
return ignoreNonDocumented;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.parchmentmc.feather.io.jackson.modules;

import org.parchmentmc.feather.io.jackson.FeatherModule;
import org.parchmentmc.feather.io.jackson.modules.metadata.*;
import org.parchmentmc.feather.io.jackson.util.BaseModule;
import org.parchmentmc.feather.metadata.*;
import org.parchmentmc.feather.named.Named;

public class MetadataModule extends BaseModule {

public MetadataModule() {
super("Feather$Metadata", FeatherModule.VERSION);
addDependency(new SimpleVersionModule());

addSerializer(Named.class, new NamedSerializer());
addDeserializer(Named.class, new NamedDeserializer());
addSerializer(SourceMetadata.class, new SourceMetadataSerializer());
addDeserializer(SourceMetadata.class, new SourceMetadataDeserializer());
addSerializer(ClassMetadata.class, new ClassMetadataSerializer());
addDeserializer(ClassMetadata.class, new ClassMetadataDeserializer());
addSerializer(FieldMetadata.class, new FieldMetadataSerializer());
addDeserializer(FieldMetadata.class, new FieldMetadataDeserializer());
addSerializer(MethodMetadata.class, new MethodMetadataSerializer());
addDeserializer(MethodMetadata.class, new MethodMetadataDeserializer());
addSerializer(Reference.class, new ReferenceSerializer());
addDeserializer(Reference.class, new ReferenceDeserializer());
addSerializer(BouncingTargetMetadata.class, new BouncingTargetMetadataSerializer());
addDeserializer(BouncingTargetMetadata.class, new BouncingTargetMetadataDeserializer());
addSerializer(RecordMetadata.class, new RecordMetadataSerializer());
addDeserializer(RecordMetadata.class, new RecordMetadataDeserializer());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.parchmentmc.feather.io.jackson.modules;

import org.parchmentmc.feather.io.jackson.FeatherModule;
import org.parchmentmc.feather.io.jackson.modules.datetime.OffsetDateTimeDeserializer;
import org.parchmentmc.feather.io.jackson.modules.datetime.OffsetDateTimeSerializer;
import org.parchmentmc.feather.io.jackson.util.BaseModule;

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class OffsetDateTimeModule extends BaseModule {

public OffsetDateTimeModule() {
this(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
}

/**
* @param formatter formatter used to serialize and deserialize OffsetDateTime.
*/
public OffsetDateTimeModule(DateTimeFormatter formatter) {
super("Feather$OffsetDateTime", FeatherModule.VERSION);
addSerializer(OffsetDateTime.class, new OffsetDateTimeSerializer(formatter));
addDeserializer(OffsetDateTime.class, new OffsetDateTimeDeserializer(formatter));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.parchmentmc.feather.io.jackson.modules;

import org.parchmentmc.feather.io.jackson.FeatherModule;
import org.parchmentmc.feather.io.jackson.modules.version.SimpleVersionDeserializer;
import org.parchmentmc.feather.io.jackson.modules.version.SimpleVersionSerializer;
import org.parchmentmc.feather.io.jackson.util.BaseModule;
import org.parchmentmc.feather.util.SimpleVersion;

public class SimpleVersionModule extends BaseModule {

public SimpleVersionModule() {
super("Feather$SimpleVersion", FeatherModule.VERSION);
addSerializer(SimpleVersion.class, new SimpleVersionSerializer());
addDeserializer(SimpleVersion.class, new SimpleVersionDeserializer());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.parchmentmc.feather.io.jackson.modules.datetime;

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class OffsetDateTimeDeserializer extends FromStringDeserializer<OffsetDateTime> {

private final DateTimeFormatter formatter;

public OffsetDateTimeDeserializer(DateTimeFormatter formatter) {
super(OffsetDateTime.class);
this.formatter = formatter;
}

@Override
protected OffsetDateTime _deserialize(String value, DeserializationContext ctxt) {
return OffsetDateTime.parse(value, formatter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.parchmentmc.feather.io.jackson.modules.datetime;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;

import java.io.IOException;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class OffsetDateTimeSerializer extends StdScalarSerializer<OffsetDateTime> {

private final DateTimeFormatter formatter;

public OffsetDateTimeSerializer(DateTimeFormatter formatter) {
super(OffsetDateTime.class);
this.formatter = formatter;
}

@Override
public void serialize(OffsetDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(formatter.format(value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.parchmentmc.feather.io.jackson.modules.mdc;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.parchmentmc.feather.io.jackson.util.CommonTypes;
import org.parchmentmc.feather.io.jackson.util.Jackson;
import org.parchmentmc.feather.mapping.ImmutableMappingDataContainer;
import org.parchmentmc.feather.mapping.MappingDataContainer;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class ClassDataDeserializer extends StdDeserializer<MappingDataContainer.ClassData> {

public ClassDataDeserializer() {
super(MappingDataContainer.ClassData.class);
}

@Override
public MappingDataContainer.ClassData deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
ObjectNode node = Jackson.getObjectNode(p);
if (node == null) return null;

String name = null;
List<String> javadoc = null;
Collection<? extends MappingDataContainer.FieldData> fields = null;
Collection<? extends MappingDataContainer.MethodData> methods = null;

final Iterator<String> propertyNames = node.fieldNames();
while (propertyNames.hasNext()) {
final String propertyName = propertyNames.next();
switch (propertyName) {
case "name":
name = node.get(propertyName).asText();
break;
case "javadoc":
javadoc = ctxt.readTreeAsValue(node.get(propertyName), CommonTypes.LIST_STRING);
break;
case "fields":
fields = ctxt.readTreeAsValue(node.get(propertyName), CommonTypes.COLLECTION_FIELD_DATA);
break;
case "methods":
methods = ctxt.readTreeAsValue(node.get(propertyName), CommonTypes.COLLECTION_METHOD_DATA);
break;
default:
// do nothing
break;
}
}

if (name == null) throw new JsonParseException("Class name must not be null");
if (javadoc == null) javadoc = Collections.emptyList();
if (fields == null) fields = Collections.emptyList();
if (methods == null) methods = Collections.emptyList();

return new ImmutableMappingDataContainer.ImmutableClassData(name, javadoc, fields, methods);
}
}
Loading

0 comments on commit be43dbf

Please sign in to comment.