Skip to content

Commit

Permalink
Merge pull request #56 from kbss-cvut/development
Browse files Browse the repository at this point in the history
0.12.3 release
  • Loading branch information
ledsoft authored Apr 6, 2023
2 parents cd27448 + 4fe7b85 commit 009ffcb
Show file tree
Hide file tree
Showing 33 changed files with 529 additions and 200 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# JB4JSON-LD Changelog

## 0.12.3 - 2023-04-06
- Support serializing individuals as string with an extended term definition in context (Enhancement #54).
- Fix serialization of types when parent context specifies term mapping.
- Remove unused JSON node creation methods.

## 0.12.2 - 2023-03-30
- Fix an issue with context embedding (Bug #51).

Expand Down
52 changes: 28 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,25 @@

Java Binding for JSON-LD (JB4JSON-LD) is a simple library for serialization of Java objects into JSON-LD and vice versa.

Note that this is the core, abstract implementation. For actual usage, a binding like [JB4JSON-LD Jackson](https://github.com/kbss-cvut/jb4jsonld-jackson)
Note that this is the core, abstract implementation. For actual usage, a binding
like [JB4JSON-LD Jackson](https://github.com/kbss-cvut/jb4jsonld-jackson)
has to be used.


## Usage

JB4JSON-LD is based on annotations from [JOPA](https://github.com/kbss-cvut/jopa), which enable POJO attributes
to be mapped to ontological constructs (i.e. to object, data or annotation properties) and Java classes to ontological
JB4JSON-LD is based on annotations from [JOPA](https://github.com/kbss-cvut/jopa), which enable POJO attributes to be
mapped to ontological constructs (i.e. to object, data or annotation properties) and Java classes to ontological
classes.

Use `@OWLDataProperty` to annotate data fields and `@OWLObjectProperty` to annotate fields referencing other mapped entities.
You can mark DTOs with `@NonEntity` to tell JOPA to ignore such classes completely (e.g., they will be ignored when AspectJ
is inserting JOPA-specific join points into entity classes).

See [https://github.com/kbss-cvut/jopa-examples/tree/master/jsonld](https://github.com/kbss-cvut/jopa-examples/tree/master/jsonld) for
an executable example of JB4JSON-LD in action (together with Spring and Jackson). The [JB4JSON-LD Jackson](https://github.com/kbss-cvut/jb4jsonld-jackson)
repository also contains a bare-bones example of setting the library up with Jackson (two DTO classes and a short Main class).
Use `@OWLDataProperty` to annotate data fields and `@OWLObjectProperty` to annotate fields referencing other mapped
entities. You can mark DTOs with `@NonEntity` to tell JOPA to ignore such classes completely (e.g., they will be ignored
when AspectJ is inserting JOPA-specific join points into entity classes).

See [https://github.com/kbss-cvut/jopa-examples/tree/master/jsonld](https://github.com/kbss-cvut/jopa-examples/tree/master/jsonld)
for an executable example of JB4JSON-LD in action (together with Spring and Jackson).
The [JB4JSON-LD Jackson](https://github.com/kbss-cvut/jb4jsonld-jackson)
repository also contains a bare-bones example of setting the library up with Jackson (two DTO classes and a short Main
class).

## Example

Expand Down Expand Up @@ -90,22 +91,24 @@ public class User {

## Configuration

| Parameter | Default value | Explanation |
|----------------------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ignoreUnknownProperties` | `false` | Whether to ignore unknown properties when deserializing JSON-LD. Default behavior throws an exception. |
| `scanPackage` | `""` | Package in which the library should look for mapped classes. The scan is important for support for polymorphism in object deserialization. It is highly recommended to specify this value, otherwise the library will attempt to load and scan all classes on the classpath. |
| `requireId` | `false` | Whether to require an identifier when serializing an object. If set to `true` and no identifier is found (either there is no `@Id` field or its value is `null`), an exception will be thrown. By default a blank node identifier is generated if no id is present. |
| `assumeTargetType` | `false` | Whether to allow assuming target type in case the JSON-LD object does not contain types (`@type`). If set to `true`, the provided Java type (deserialization invocation argument, field type) will be used as target type. |
| `enableOptimisticTargetTypeResolution` | `false` | Whether to enable optimistic target type resolution. If enabled, this allows to pick a target type even if there are multiple matching classes (which would normally end with an `AmbiguousTargetTypeException`). |
| `preferSuperclass` | `false` | Allows to further specify optimistic target type resolution. By default, any of the target classes may be selected. Setting this to `true` will make the resolver attempt to select a superclass of the matching classes (if it is also in the target set). |
| `serializeDatetimeAsMillis` | `false` | Whether to serialize datetime values as millis since Unix epoch. If false, datetime value are serialize as string in ISO format (default). |
| `datetimeFormat` | | Format in which datetime values are serialized (and expected for deserialization). Default is undefined, meaning that the ISO 8601 format is used. |
| Parameter | Default value | Explanation |
|----------------------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ignoreUnknownProperties` | `false` | Whether to ignore unknown properties when deserializing JSON-LD. Default behavior throws an exception. |
| `scanPackage` | `""` | Package in which the library should look for mapped classes. The scan is important for support for polymorphism in object deserialization. It is highly recommended to specify this value, otherwise the library will attempt to load and scan all classes on the classpath. |
| `requireId` | `false` | Whether to require an identifier when serializing an object. If set to `true` and no identifier is found (either there is no `@Id` field or its value is `null`), an exception will be thrown. By default a blank node identifier is generated if no id is present. |
| `assumeTargetType` | `false` | Whether to allow assuming target type in case the JSON-LD object does not contain types (`@type`). If set to `true`, the provided Java type (deserialization invocation argument, field type) will be used as target type. |
| `enableOptimisticTargetTypeResolution` | `false` | Whether to enable optimistic target type resolution. If enabled, this allows to pick a target type even if there are multiple matching classes (which would normally end with an `AmbiguousTargetTypeException`). |
| `preferSuperclass` | `false` | Allows to further specify optimistic target type resolution. By default, any of the target classes may be selected. Setting this to `true` will make the resolver attempt to select a superclass of the matching classes (if it is also in the target set). |
| `serializeDatetimeAsMillis` | `false` | Whether to serialize datetime values as millis since Unix epoch. If false, datetime value are serialize as string in ISO format (default). |
| `datetimeFormat` | | Format in which datetime values are serialized (and expected for deserialization). Default is undefined, meaning that the ISO 8601 format is used. |
| `serializeIndividualsUsingExpandedDefinition` | `false` | Whether individuals should be serialized as string with expanded term definition in context (consisting of `@id` and `@type`) Relevant only for context-based serializer. |

See `cz.cvut.kbss.jsonld.ConfigParam`.

## Documentation

Documentation is on the [Wiki](https://github.com/kbss-cvut/jb4jsonld/wiki). API Javadoc is also [available](https://kbss.felk.cvut.cz/jenkins/view/Java%20Tools/job/jaxb-jsonld/javadoc/).
Documentation is on the [Wiki](https://github.com/kbss-cvut/jb4jsonld/wiki). API Javadoc is
also [available](https://kbss.felk.cvut.cz/jenkins/view/Java%20Tools/job/jaxb-jsonld/javadoc/).

## Getting JB4JSON-LD

Expand All @@ -115,14 +118,15 @@ There are two ways to get JB4JSON-LD:
* Use a [Maven dependency](http://search.maven.org/#search%7Cga%7C1%7Ccz.cvut.kbss.jsonld):

```XML

<dependency>
<groupId>cz.cvut.kbss.jsonld</groupId>
<artifactId>jb4jsonld</artifactId>
</dependency>
```

Note that you will most likely need an integration with a JSON-serialization library like [JB4JSON-LD-Jackson](https://github.com/kbss-cvut/jb4jsonld-jackson).

Note that you will most likely need an integration with a JSON-serialization library
like [JB4JSON-LD-Jackson](https://github.com/kbss-cvut/jb4jsonld-jackson).

## License

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>cz.cvut.kbss.jsonld</groupId>
<artifactId>jb4jsonld</artifactId>
<version>0.12.2</version>
<version>0.12.3</version>
<name>JB4JSON-LD</name>
<description>Java Binding for JSON-LD allows serialization and deserialization of Java POJOs to/from JSON-LD.
This is the core implementation, which has to be integrated with Jackson, Jersey etc.
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/cz/cvut/kbss/jsonld/ConfigParam.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,15 @@ public enum ConfigParam {
* <p>
* Also note that this format applies only to full datetime values. Date or time values have to be formatted per-attribute.
*/
DATE_TIME_FORMAT("datetimeFormat");
DATE_TIME_FORMAT("datetimeFormat"),

/**
* Whether to serialize individuals using expanded term definition in context.
*
* This basically means that the individual's identifier is provided directly as a string and an expanded term
* definition (consisting of a {@literal @id} and {@literal @type}) is added into the context, specifying that the string is an identifier.
*/
SERIALIZE_INDIVIDUALS_USING_EXPANDED_DEFINITION("serializeIndividualsUsingExpandedDefinition");

private final String name;

Expand Down
12 changes: 12 additions & 0 deletions src/main/java/cz/cvut/kbss/jsonld/common/BeanClassProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,18 @@ public static void verifyPropertiesFieldType(Field field) {
}
}

/**
* Checks whether the specified class represents an individual reference and not a complex object.
*
* Individual references are identifiers or enum constants mapped to individuals.
* @param cls Class to check
* @return {@code true} when the type represents an individual, {@code false} otherwise
* @see #isIdentifierType(Class)
*/
public static boolean isIndividualType(Class<?> cls) {
return isIdentifierType(cls) || cls.isEnum();
}

/**
* Checks whether the specified type is a valid identifier type.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ protected ValueSerializers initSerializers() {
new LiteralValueSerializers(new DefaultValueSerializer(new MultilingualStringSerializer()));
valueSerializers.registerIdentifierSerializer(new IdentifierSerializer());
valueSerializers.registerTypesSerializer(new TypesSerializer());
valueSerializers.registerIndividualSerializer(new IndividualSerializer());
final TemporalSerializer ts = new TemporalSerializer();
valueSerializers.registerSerializer(LocalDate.class, ts);
// Register the same temporal serializer for each of the types it supports (needed for key-based map access)
Expand All @@ -72,12 +73,16 @@ protected JsonNode buildJsonTree(Object root) {
final ObjectGraphTraverser traverser = new ObjectGraphTraverser(new SerializationContextFactory(
DummyJsonLdContext.INSTANCE));
traverser.setRequireId(configuration().is(ConfigParam.REQUIRE_ID));
final JsonLdTreeBuilder treeBuilder =
new JsonLdTreeBuilder(
new ObjectGraphValueSerializers(serializers, new ObjectPropertyValueSerializer(traverser)),
DummyJsonLdContext.INSTANCE);
final JsonLdTreeBuilder treeBuilder = initTreeBuilder(traverser);
traverser.setVisitor(treeBuilder);
traverser.traverse(root);
return treeBuilder.getTreeRoot();
}

private JsonLdTreeBuilder initTreeBuilder(ObjectGraphTraverser traverser) {
final ObjectPropertyValueSerializer opSerializer = new ObjectPropertyValueSerializer(traverser);
opSerializer.configure(configuration());
return new JsonLdTreeBuilder(new ObjectGraphValueSerializers(serializers, opSerializer),
DummyJsonLdContext.INSTANCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ protected ValueSerializers initSerializers() {
new LiteralValueSerializers(new ContextBuildingDefaultValueSerializer(mlsSerializer, mlsColSerializer));
valueSerializers.registerIdentifierSerializer(new ContextBuildingIdentifierSerializer());
valueSerializers.registerTypesSerializer(new ContextBuildingTypesSerializer());
valueSerializers.registerIndividualSerializer(new ContextBuildingIndividualSerializer());
final ContextBuildingTemporalSerializer ts = new ContextBuildingTemporalSerializer();
valueSerializers.registerSerializer(LocalDate.class, ts);
// Register the same temporal serializer for each of the types it supports (needed for key-based map access)
Expand Down Expand Up @@ -96,9 +97,9 @@ private void ensureContextNodeNotPresent(CompositeNode<?> root, JsonNode rootCtx

private JsonLdTreeBuilder initTreeBuilder(ObjectGraphTraverser traverser,
JsonLdContextFactory jsonLdContextFactory) {
return new JsonLdTreeBuilder(new ObjectGraphValueSerializers(serializers,
new ContextBuildingObjectPropertyValueSerializer(
traverser)), jsonLdContextFactory);
final ContextBuildingObjectPropertyValueSerializer opSerializer = new ContextBuildingObjectPropertyValueSerializer(traverser);
opSerializer.configure(configuration());
return new JsonLdTreeBuilder(new ObjectGraphValueSerializers(serializers, opSerializer), jsonLdContextFactory);
}

private JsonNode buildObjectWithContextAndGraph(ObjectGraphTraverser traverser, JsonLdContext rootContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ public JsonLdTreeBuilder(ValueSerializers serializers, JsonLdContextFactory json
this.jsonLdContextFactory = jsonLdContextFactory;
}

@Override
public void visitIndividual(SerializationContext<?> ctx) {
final ValueSerializer s = serializers.getIndividualSerializer();
final JsonNode node = s.serialize(ctx.getValue(), ctx);
if (currentNode != null) {
currentNode.addItem(node);
} else {
assert node instanceof CompositeNode;
currentNode = (CompositeNode<?>) node;
}
}

@Override
public boolean visitObject(SerializationContext<?> ctx) {
if (serializers.hasCustomSerializer(ctx.getValue().getClass())) {
Expand All @@ -63,8 +75,7 @@ public boolean visitObject(SerializationContext<?> ctx) {

@Override
public void openObject(SerializationContext<?> ctx) {
final ObjectNode newCurrent = ctx.getTerm() != null ? JsonNodeFactory.createObjectNode(ctx.getTerm()) :
JsonNodeFactory.createObjectNode();
final ObjectNode newCurrent = JsonNodeFactory.createObjectNode(ctx.getTerm());
openNewNode(newCurrent);
// Prepare to create new JSON-LD context when an object is open
ctx.setJsonLdContext(jsonLdContextFactory.createJsonLdContext(ctx.getJsonLdContext()));
Expand Down Expand Up @@ -120,10 +131,7 @@ public void visitAttribute(SerializationContext<?> ctx) {

@Override
public void openCollection(SerializationContext<? extends Collection<?>> ctx) {
final CollectionNode<?> newCurrent =
ctx.getTerm() != null ? JsonNodeFactory.createCollectionNode(ctx.getTerm(),
ctx.getValue()) :
JsonNodeFactory.createCollectionNode(ctx.getValue());
final CollectionNode<?> newCurrent =JsonNodeFactory.createCollectionNode(ctx.getTerm(), ctx.getValue());
openNewNode(newCurrent);
}

Expand Down
Loading

0 comments on commit 009ffcb

Please sign in to comment.