# HG changeset patch # User cin # Date 2025-11-10 07:14:54 # Node ID fbdc61892d72e86ab18d0a04af9edb2afc9015b1 # Parent 8e171ef3106fd90a4890a3548af6e99dd4aea01a added jackson and Json traits class diff --git a/common/build.gradle b/common/build.gradle --- a/common/build.gradle +++ b/common/build.gradle @@ -7,13 +7,15 @@ java { withJavadocJar() withSourcesJar() toolchain { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) } } dependencies { compileOnly libs.jdt.annotations + implementation libs.bundles.jackson + api gradleApi() } diff --git a/common/src/main/java/org/implab/gradle/common/utils/Json.java b/common/src/main/java/org/implab/gradle/common/utils/Json.java new file mode 100644 --- /dev/null +++ b/common/src/main/java/org/implab/gradle/common/utils/Json.java @@ -0,0 +1,126 @@ +package org.implab.gradle.common.utils; + +import java.io.File; +import java.io.IOException; +import java.util.function.Consumer; + +import org.implab.gradle.common.utils.LazyValue; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.core.util.DefaultIndenter; +import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; + +public class Json { + + private final static LazyValue mapper = new LazyValue<>(Json::createMapper); + + private static ObjectMapper createMapper() { + DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter(); + prettyPrinter.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE); + + return new ObjectMapper() + .registerModule(new Jdk8Module()) + .registerModule(new JavaTimeModule()) + .setSerializationInclusion(Include.NON_EMPTY) + .enable(SerializationFeature.INDENT_OUTPUT) + .setDefaultPrettyPrinter(prettyPrinter); + } + + public static ObjectMapper jsonMapper() { + return mapper.get(); + } + + public static Consumer fileWriter(Object value) { + return file -> { + try { + jsonMapper().writeValue(file, value); + } catch (IOException e) { + throw new SerializationException(e); + } + }; + } + + public static void write(File file, Object value) { + try { + jsonMapper().writeValue(file, value); + } catch (IOException e) { + throw new SerializationException(e); + } + } + + public static String stringify(Object value) { + try { + return jsonMapper().writeValueAsString(value); + } catch (JsonProcessingException e) { + throw new SerializationException(e); + } + } + + public static T parse(String json, Class clazz) { + try { + return jsonMapper().readValue(json, clazz); + } catch (JsonProcessingException e) { + throw new SerializationException(e); + } + } + + public static T parse(String json, TypeReference type) { + try { + return jsonMapper().readValue(json, type); + } catch (JsonProcessingException e) { + throw new SerializationException(e); + } + } + + public static T read(File file, TypeReference type) { + try { + return jsonMapper().readValue(file, type); + } catch (IOException e) { + throw new SerializationException(e); + } + } + + public static T updateValue(T target, Object source) { + try { + return jsonMapper().updateValue(target, source); + } catch (JsonMappingException e) { + throw new SerializationException(e); + } + } + + public static T convertValue(Object source, Class clazz) { + var mapper = jsonMapper(); + var buf = mapper.getSerializerProvider().bufferForValueConversion(jsonMapper()); + + try { + mapper.writeValue(buf, source); + return mapper.readValue(buf.asParser(), clazz); + } catch (IOException e) { + throw new SerializationException(e); + } + } + + public static class SerializationException extends RuntimeException { + public SerializationException() { + } + + public SerializationException(String message) { + super(message); + } + + public SerializationException(Throwable cause) { + super(cause); + } + + public SerializationException(String message, Throwable cause) { + super(message, cause); + } + } +} diff --git a/common/src/main/java/org/implab/gradle/common/utils/Properties.java b/common/src/main/java/org/implab/gradle/common/utils/Properties.java --- a/common/src/main/java/org/implab/gradle/common/utils/Properties.java +++ b/common/src/main/java/org/implab/gradle/common/utils/Properties.java @@ -14,15 +14,10 @@ public final class Properties { } public static void mergeMap(MapProperty property, Map map) { - map.forEach((k, v) -> { - if (v instanceof Provider) - property.put(k, (Provider) v); - else - property.put(k, v); - }); + mergeMap(property, map, Function.identity()); } - public static void mergeMap(MapProperty property, Map map, Function mapper) { + public static void mergeMap(MapProperty property, Map map, Function mapper) { map.forEach((k, v) -> { if (v instanceof Provider) property.put(k, ((Provider) v).map(mapper::apply)); @@ -32,15 +27,10 @@ public final class Properties { } public static void mergeList(ListProperty property, Iterable values) { - values.forEach(v -> { - if (v instanceof Provider) - property.add((Provider) v); - else - property.add(v); - }); + mergeList(property, values, Function.identity()); } - public static void mergeList(ListProperty property, Iterable values, Function mapper) { + public static void mergeList(ListProperty property, Iterable values, Function mapper) { values.forEach(v -> { if (v instanceof Provider) property.add(((Provider) v).map(mapper::apply)); @@ -50,9 +40,7 @@ public final class Properties { } public static void configureMap(MapProperty prop, Action> configure) { - var map = new HashMap(); - configure.execute(map); - mergeMap(prop, map); + configureMap(prop, configure, Function.identity()); } public static void configureMap(MapProperty prop, Action> configure, Function mapper) { diff --git a/common/src/main/java/org/implab/gradle/common/utils/Values.java b/common/src/main/java/org/implab/gradle/common/utils/Values.java --- a/common/src/main/java/org/implab/gradle/common/utils/Values.java +++ b/common/src/main/java/org/implab/gradle/common/utils/Values.java @@ -60,10 +60,6 @@ public final class Values { return provider.get(); } - public static Set mapSet(Set values, Function mapper) { - return values.stream().map(mapper).collect(Collectors.toUnmodifiableSet()); - } - private static class ArrayIterator implements Iterator { private final T[] data; diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,17 @@ [versions] immutables = "2.10.1" jdt = "2.3.0" +jackson = "2.15.4" [libraries] immutables = { module = "org.immutables:value", version.ref = "immutables" } jdt-annotations = { module = "org.eclipse.jdt:org.eclipse.jdt.annotation", version.ref = "jdt" } + +#jackson +jackson-core = { module = "com.fasterxml.jackson.core:jackson-core", version.ref = "jackson" } +jackson-datatype-jdk8 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jdk8", version.ref = "jackson" } +jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" } + +[bundles] + +jackson = ["jackson-core", "jackson-datatype-jdk8", "jackson-datatype-jsr310"] \ No newline at end of file