Is json-ld compatibe to json-ld and what does activityPub understand with json-ld

unfortunately i keep running into problems with parsing json-ld and the problem that others can’t interpret “my” json-ld. if i take “my” json-ld and paste it into JSON-LD Playground everything seems to be ok.
So it looks like activityPub implementations speak a different json-ld. But I have the feeling that this json-ld is not specified.
Am I the only one with this problem?
I don’t want to write a json-ld parser/generator, but use libraries that exist and are provided in the RDF context. At the moment I rely on GitHub - jsonld-java/jsonld-java: JSON-LD implementation for Java which is used in the context of rdf4j.

Framing does not seem to solve the problem either. At least it didn’t with Pleroma.

https://www.w3.org/TR/activitystreams-core (section 2.1) specifies the rules that ActivityPub documents need to conform to be considered valid. Tl;dr: It’s a specific subset of JSON-LD based on compacting it to the normative context “http://www.w3.org/ns/activitystreams

Today i found a way to be more compatible. titanium seems to do it’s job well!

Converting my RDF Model into the compact format like that:

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.eclipse.rdf4j.rio.Rio;
import org.springframework.core.io.ClassPathResource;

import com.apicatalog.jsonld.JsonLd;
import com.apicatalog.jsonld.document.Document;
import com.apicatalog.jsonld.document.JsonDocument;

import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonWriter;
import jakarta.json.JsonWriterFactory;
import jakarta.json.stream.JsonGenerator;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ApModelTools {

	/**
	 * Converts the passed model into a ActivityPub optimized string.
	 * @param model The RDF4J Model
	 * @param rdfFormat The format to convert to
	 * @return The model as string.
	 */
	public static String toString(Model model, RDFFormat rdfFormat) {
		
		String modelAsString = modelToString(model, rdfFormat);
		if(RDFFormat.JSONLD.equals(rdfFormat)) {
			modelAsString = compact(modelAsString);	
		}
		return modelAsString;
	}

	/**
	 * Converts the passed model into a string.
	 * That can be a none optimized string for example in case of json-ld.
	 * @param model The RDF4J Model
	 * @param rdfFormat The format to convert to
	 * @return The model as string.
	 */
	private static String modelToString(Model model, RDFFormat rdfFormat) {
		StringWriter sw = new StringWriter();
		Rio.write(model, sw, rdfFormat);
		String modelAsString = sw.toString();
		return modelAsString;
	}
		
	/**
	 * Converts the passed json-ld string into a <a href="https://www.w3.org/TR/json-ld/#compacted-document-form">compact</a> one.
	 * @param rdf4jJsonLd string to be compacted
	 * @return the compacted string or the input stream, if there was an error while converting. The error will be logged!
	 */
	private static String compact(String rdf4jJsonLd) {
		try {
			Document document = JsonDocument.of(new StringReader(rdf4jJsonLd));
			Document frame = JsonDocument.of(new ClassPathResource("as.jsonld").getInputStream());
			return jsonObjectToString(JsonLd.compact(document, frame)
		      .ordered()
		      .get());
		} catch (Exception e) {
			log.error("error compacting jsonLd", e);
			return rdf4jJsonLd;
		}
	}
	
	/**
	 * Converts the passed {@link JsonObject} into a pretty printed string.
	 * @param json object to convert
	 * @return a pretty printed string
	 * @throws IOException
	 */
	private static String jsonObjectToString(JsonObject json) throws IOException	{
	    Map<String,Boolean> config = new HashMap<>();
	    config.put(JsonGenerator.PRETTY_PRINTING, true);
	 
	    JsonWriterFactory writerFactory = Json.createWriterFactory(config);
	    try (Writer stringWriter = new StringWriter(); 
	         JsonWriter jsonWriter = writerFactory.createWriter(stringWriter)) {
	        jsonWriter.write(json);
	        return stringWriter.toString();
	    }
	}		
}

as.jsonld is more or less the same as:

curl --location --request GET 'http://www.w3.org/ns/activitystreams' \
--header 'Accept: application/ld+json'

Just with a small fix from @pukkamustard

So i’m again motivated to try some stuff with e.g. pleroma.

Thanks to @cjs

2 Likes

Feature request for titanium-json-ld to create something AS/AP compatible

One should never give up
A wonderful weekend to you all