JSON SPI
Every jsass setup needs a JSON deserializer, and the reason is not obvious: jsass reads
package.json files. Both module resolvers have to find a package's entry point before they can
hand its JavaScript to the engine, and that entry point is declared in package.json — inside the
sass WebJar for the V8 route, inside node_modules/sass/ for the Node route.
Rather than bundling a JSON parser and forcing a version on you, jsass declares a one-method SPI:
public interface JsonDeserializer {
Map<String, Object> deserialize(InputStream inputStream) throws IOException;
}
Pick an implementation
| Artifact | Class | Runs on |
|---|---|---|
jsass.jackson2 |
Jackson2JsonDeserializer |
Jackson 2.x (com.fasterxml.jackson) |
jsass.jackson3 |
Jackson3JsonDeserializer |
Jackson 3.x (tools.jackson) |
Take the one that matches the Jackson your application already has — Spring Boot 3, for
instance, ships Jackson 2. If you have neither, jsass.jackson2 is the safe default.
var moduleResolver = WebjarV8ModuleResolver.builder()
.jsonDeserializer(new Jackson2JsonDeserializer())
.build();
Both implementations are stateless and thread-safe; one instance per application is plenty.
Bring your own
The SPI is small enough that any JSON library will do — Gson, JSON-B, Moshi, a hand-written parser. Implement the interface and pass it to the resolver:
public class GsonJsonDeserializer implements JsonDeserializer {
private static final Type MAP_TYPE = new TypeToken<Map<String, Object>>() {}.getType();
private final Gson gson = new Gson();
@Override
public Map<String, Object> deserialize(InputStream inputStream) throws IOException {
try (var reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
return gson.fromJson(reader, MAP_TYPE);
}
}
}
Only the keys a package.json uses to declare its entry point are ever read, so a plain nested
Map is all the SPI has to produce.