initial commit
This commit is contained in:
commit
3ee456bd8f
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# ---> Gradle
|
||||||
|
.gradle
|
||||||
|
**/build/
|
||||||
|
!src/**/build/
|
||||||
|
|
||||||
|
# Ignore Gradle GUI config
|
||||||
|
gradle-app.setting
|
||||||
|
|
||||||
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
!gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Avoid ignore Gradle wrappper properties
|
||||||
|
!gradle-wrapper.properties
|
||||||
|
|
||||||
|
# Cache of project
|
||||||
|
.gradletasknamecache
|
||||||
|
|
||||||
|
# Eclipse Gradle plugin generated files
|
||||||
|
# Eclipse Core
|
||||||
|
.project
|
||||||
|
# JDT-specific (Eclipse Java Development Tools)
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
# ---> Java
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
replay_pid*
|
||||||
|
|
27
core/build.gradle.kts
Normal file
27
core/build.gradle.kts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
plugins {
|
||||||
|
`java-library`
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "eu.jonahbauer"
|
||||||
|
version = "1.0-SNAPSHOT"
|
||||||
|
description = "json"
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(22)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api(libs.annotations)
|
||||||
|
|
||||||
|
compileOnly(libs.lombok)
|
||||||
|
annotationProcessor(libs.lombok)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
withType<JavaCompile> {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
options.compilerArgs.add("--enable-preview")
|
||||||
|
}
|
||||||
|
}
|
394
core/src/main/java/eu/jonahbauer/json/JsonArray.java
Normal file
394
core/src/main/java/eu/jonahbauer/json/JsonArray.java
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
package eu.jonahbauer.json;
|
||||||
|
|
||||||
|
import eu.jonahbauer.json.exceptions.JsonConversionException;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java representation of a JSON array.
|
||||||
|
* @param elements the array's elements
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public record JsonArray(
|
||||||
|
@NotNull List<? extends @Nullable JsonValue> elements
|
||||||
|
) implements JsonValue, List<@Nullable JsonValue> {
|
||||||
|
public static final @NotNull JsonArray EMPTY = new JsonArray(List.of());
|
||||||
|
|
||||||
|
public JsonArray {
|
||||||
|
Objects.requireNonNull(elements, "elements");
|
||||||
|
elements = Util.defensiveCopy(elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull JsonArray of(@Nullable JsonValue @NotNull... elements) {
|
||||||
|
return new JsonArray(Arrays.stream(elements).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
//<editor-fold desc="valueOf(...)" defaultstate="collapsed">
|
||||||
|
/**
|
||||||
|
* Creates a JSON array from the given list, using {@link JsonValue#valueOf(Object)} to convert the objects to
|
||||||
|
* {@link JsonValue}s.
|
||||||
|
* @param list a list of objects
|
||||||
|
* @return a new JSON array
|
||||||
|
* @throws JsonConversionException if the given list or its entries cannot be converted to json
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(@Nullable List<?> list) {
|
||||||
|
if (list == null) return null;
|
||||||
|
if (list instanceof JsonArray json) return json;
|
||||||
|
return new JsonArray(list.stream().map(JsonValue::valueOf).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonValue#valueOf(Object)} to convert the objects to
|
||||||
|
* {@link JsonValue}s.
|
||||||
|
* @param array an array of objects
|
||||||
|
* @return a new JSON array
|
||||||
|
* @throws JsonConversionException if the given array or its entries cannot be converted to json
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(@Nullable Object @Nullable... array) {
|
||||||
|
return array == null ? null : new JsonArray(Arrays.stream(array).map(JsonValue::valueOf).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonBoolean#valueOf(boolean)} to convert the
|
||||||
|
* booleans to {@link JsonBoolean}s.
|
||||||
|
* @param array an array of booleans
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(boolean @Nullable... array) {
|
||||||
|
if (array == null) return null;
|
||||||
|
var list = new ArrayList<JsonValue>();
|
||||||
|
for (var b : array) {
|
||||||
|
list.add(JsonBoolean.valueOf(b));
|
||||||
|
}
|
||||||
|
return new JsonArray(Util.trusted(Collections.unmodifiableList(list)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonNumber#valueOf(int)} to convert the
|
||||||
|
* bytes to {@link JsonNumber}s.
|
||||||
|
* @param array an array of bytes
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(byte @Nullable... array) {
|
||||||
|
if (array == null) return null;
|
||||||
|
var list = new ArrayList<JsonValue>();
|
||||||
|
for (var b : array) {
|
||||||
|
list.add(JsonNumber.valueOf(b));
|
||||||
|
}
|
||||||
|
return new JsonArray(Util.trusted(Collections.unmodifiableList(list)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonNumber#valueOf(int)} to convert the
|
||||||
|
* shorts to {@link JsonNumber}s.
|
||||||
|
* @param array an array of shorts
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(short @Nullable... array) {
|
||||||
|
if (array == null) return null;
|
||||||
|
var list = new ArrayList<JsonValue>();
|
||||||
|
for (var s : array) {
|
||||||
|
list.add(JsonNumber.valueOf(s));
|
||||||
|
}
|
||||||
|
return new JsonArray(Util.trusted(Collections.unmodifiableList(list)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonString#valueOf(char)} to convert the
|
||||||
|
* chars to {@link JsonString}s.
|
||||||
|
* @param array an array of chars
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(char @Nullable... array) {
|
||||||
|
if (array == null) return null;
|
||||||
|
var list = new ArrayList<JsonValue>();
|
||||||
|
for (var c : array) {
|
||||||
|
list.add(JsonString.valueOf(c));
|
||||||
|
}
|
||||||
|
return new JsonArray(Util.trusted(Collections.unmodifiableList(list)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonNumber#valueOf(int)} to convert the
|
||||||
|
* ints to {@link JsonNumber}s.
|
||||||
|
* @param array an array of ints
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(int @Nullable... array) {
|
||||||
|
return array == null ? null : new JsonArray(Arrays.stream(array).mapToObj(JsonNumber::valueOf).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonNumber#valueOf(long)} to convert the
|
||||||
|
* longs to {@link JsonNumber}s.
|
||||||
|
* @param array an array of longs
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(long @Nullable... array) {
|
||||||
|
return array == null ? null : new JsonArray(Arrays.stream(array).mapToObj(JsonNumber::valueOf).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonNumber#valueOf(double)} to convert the
|
||||||
|
* floats to {@link JsonNumber}s.
|
||||||
|
* @param array an array of floats
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(float @Nullable... array) {
|
||||||
|
if (array == null) return null;
|
||||||
|
var list = new ArrayList<JsonValue>();
|
||||||
|
for (var f : array) {
|
||||||
|
list.add(JsonNumber.valueOf(f));
|
||||||
|
}
|
||||||
|
return new JsonArray(Util.trusted(Collections.unmodifiableList(list)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JSON array from the given array, using {@link JsonNumber#valueOf(double)} to convert the
|
||||||
|
* doubles to {@link JsonNumber}s.
|
||||||
|
* @param array an array of doubles
|
||||||
|
* @return a new JSON array
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonArray valueOf(double @Nullable... array) {
|
||||||
|
return array == null ? null : new JsonArray(Arrays.stream(array).mapToObj(JsonNumber::valueOf).toList());
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold desc="List" defaultstate="collapsed">
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return elements.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return elements.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
return elements.contains(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked") // elements is immutable
|
||||||
|
public @NotNull Iterator<@Nullable JsonValue> iterator() {
|
||||||
|
return (Iterator<JsonValue>) elements.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object @NotNull[] toArray() {
|
||||||
|
return elements.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T @NotNull[] toArray(T @NotNull[] a) {
|
||||||
|
return elements.toArray(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(@Nullable JsonValue value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("SlowListContainsAll")
|
||||||
|
public boolean containsAll(@NotNull Collection<?> c) {
|
||||||
|
return elements.containsAll(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(@NotNull Collection<? extends @Nullable JsonValue> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean addAll(int index, @NotNull Collection<? extends @Nullable JsonValue> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll(@NotNull Collection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean retainAll(@NotNull Collection<?> c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable JsonValue get(int index) {
|
||||||
|
return elements.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable JsonValue set(int index, @Nullable JsonValue element) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(int index, @Nullable JsonValue element) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable JsonValue remove(int index) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int indexOf(Object o) {
|
||||||
|
return elements.indexOf(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int lastIndexOf(Object o) {
|
||||||
|
return elements.lastIndexOf(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked") // elements is immutable
|
||||||
|
public @NotNull ListIterator<@Nullable JsonValue> listIterator() {
|
||||||
|
return (ListIterator<JsonValue>) elements.listIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked") // elements is immutable
|
||||||
|
public @NotNull ListIterator<@Nullable JsonValue> listIterator(int index) {
|
||||||
|
return (ListIterator<JsonValue>) elements.listIterator(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull JsonArray subList(int fromIndex, int toIndex) {
|
||||||
|
return new JsonArray(elements.subList(fromIndex, toIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull JsonArray reversed() {
|
||||||
|
return new JsonArray(Util.trusted(elements.reversed()));
|
||||||
|
}
|
||||||
|
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold desc="get...(int index)" defaultstate="collapsed">
|
||||||
|
/**
|
||||||
|
* {@return the element at the specified index in this array}
|
||||||
|
* @param index index of the element to return
|
||||||
|
* @throws ClassCastException if the element at the specified index is not an instance of {@link JsonString}
|
||||||
|
* @throws NullPointerException if the element at the specified index is {@code null}
|
||||||
|
* @throws IndexOutOfBoundsException if the index is less than zero or greater than or equals to the size of the array
|
||||||
|
*/
|
||||||
|
public @NotNull JsonString getString(int index) {
|
||||||
|
return get(index, JsonString.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the element at the specified index in this array}
|
||||||
|
* @param index index of the element to return
|
||||||
|
* @throws ClassCastException if the element at the specified index is not an instance of {@link JsonNumber}
|
||||||
|
* @throws NullPointerException if the element at the specified index is {@code null}
|
||||||
|
* @throws IndexOutOfBoundsException if the index is less than zero or greater than or equals to the size of the array
|
||||||
|
*/
|
||||||
|
public @NotNull JsonNumber getNumber(int index) {
|
||||||
|
return get(index, JsonNumber.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the element at the specified index in this array}
|
||||||
|
* @param index index of the element to return
|
||||||
|
* @throws ClassCastException if the element at the specified index is not an instance of {@link JsonBoolean}
|
||||||
|
* @throws NullPointerException if the element at the specified index is {@code null}
|
||||||
|
* @throws IndexOutOfBoundsException if the index is less than zero or greater than or equals to the size of the array
|
||||||
|
*/
|
||||||
|
public @NotNull JsonBoolean getBoolean(int index) {
|
||||||
|
return get(index, JsonBoolean.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the element at the specified index in this array}
|
||||||
|
* @param index index of the element to return
|
||||||
|
* @throws ClassCastException if the element at the specified index is not an instance of {@link JsonArray}
|
||||||
|
* @throws NullPointerException if the element at the specified index is {@code null}
|
||||||
|
* @throws IndexOutOfBoundsException if the index is less than zero or greater than or equals to the size of the array
|
||||||
|
*/
|
||||||
|
public @NotNull JsonArray getArray(int index) {
|
||||||
|
return get(index, JsonArray.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the element at the specified index in this array}
|
||||||
|
* @param index index of the element to return
|
||||||
|
* @throws ClassCastException if the element at the specified index is not an instance of {@link JsonObject}
|
||||||
|
* @throws NullPointerException if the element at the specified index is {@code null}
|
||||||
|
* @throws IndexOutOfBoundsException if the index is less than zero or greater than or equals to the size of the array
|
||||||
|
*/
|
||||||
|
public @NotNull JsonObject getObject(int index) {
|
||||||
|
return get(index, JsonObject.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends JsonValue> @NotNull T get(int index, @NotNull Class<T> type) {
|
||||||
|
var value = elements().get(index);
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException("Value at index" + index + " is null.");
|
||||||
|
} else {
|
||||||
|
return type.cast(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
var joiner = new StringJoiner(",", "[", "]");
|
||||||
|
for (JsonValue element : elements) {
|
||||||
|
joiner.add(JsonValue.toJsonString(element));
|
||||||
|
}
|
||||||
|
return joiner.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toPrettyJsonString() {
|
||||||
|
if (size() < 2) return toJsonString();
|
||||||
|
|
||||||
|
var out = new StringJoiner(",\n", "[\n", "\n]");
|
||||||
|
elements().forEach(e -> out.add(indent(JsonValue.toPrettyJsonString(e))));
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull String indent(@NotNull String string) {
|
||||||
|
if (string.isEmpty()) return "";
|
||||||
|
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
|
||||||
|
Iterator<String> it = string.lines().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
out.append(" ").append(it.next());
|
||||||
|
if (it.hasNext()) out.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
}
|
46
core/src/main/java/eu/jonahbauer/json/JsonBoolean.java
Normal file
46
core/src/main/java/eu/jonahbauer/json/JsonBoolean.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package eu.jonahbauer.json;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java representation of a JSON boolean.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Accessors(fluent = true)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum JsonBoolean implements JsonValue {
|
||||||
|
TRUE(true),
|
||||||
|
FALSE(false),
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given boolean to a JSON boolean.
|
||||||
|
* @param bool a boolean
|
||||||
|
* @return a JSON boolean
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonBoolean valueOf(boolean bool) {
|
||||||
|
return bool ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given boolean to a JSON boolean.
|
||||||
|
* @param bool a boolean
|
||||||
|
* @return a JSON boolean
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonBoolean valueOf(@Nullable Boolean bool) {
|
||||||
|
return bool == null ? null : valueOf((boolean) bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final boolean value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
return String.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
63
core/src/main/java/eu/jonahbauer/json/JsonNumber.java
Normal file
63
core/src/main/java/eu/jonahbauer/json/JsonNumber.java
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package eu.jonahbauer.json;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java representation of a JSON boolean. Note, that JSON does not distinguish between integers and floating point
|
||||||
|
* numbers and therefore all numbers are stored as {@code double}.
|
||||||
|
*/
|
||||||
|
public record JsonNumber(double value) implements JsonValue {
|
||||||
|
public JsonNumber {
|
||||||
|
if (!Double.isFinite(value)) throw new IllegalArgumentException("value must be finite");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given int to a JSON number.
|
||||||
|
* @param i an int
|
||||||
|
* @return a new JSON number
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonNumber valueOf(int i) {
|
||||||
|
return new JsonNumber(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given long to a JSON number.
|
||||||
|
* @param l a long
|
||||||
|
* @return a new JSON number
|
||||||
|
* @throws IllegalArgumentException if conversion from {@code long} to {@code double} is lossy
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonNumber valueOf(long l) {
|
||||||
|
if ((long) (double) l != l) {
|
||||||
|
throw new IllegalArgumentException("lossy conversion from long to double for value " + l);
|
||||||
|
}
|
||||||
|
return new JsonNumber(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given double to a JSON number.
|
||||||
|
* @param d a double
|
||||||
|
* @return a new JSON number
|
||||||
|
* @throws IllegalArgumentException if {@code d} is not {@linkplain Double#isFinite(double) finite}
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonNumber valueOf(double d) {
|
||||||
|
return new JsonNumber(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given number to a JSON number using {@link Number#doubleValue()}. The conversion to a JSON number
|
||||||
|
* might be lossy.
|
||||||
|
* @param number a number
|
||||||
|
* @return a new JSON number
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonNumber valueOf(@Nullable Number number) {
|
||||||
|
return number == null ? null : new JsonNumber(number.doubleValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
return (long) value == value ? Long.toString((long) value) : Double.toString(value);
|
||||||
|
}
|
||||||
|
}
|
377
core/src/main/java/eu/jonahbauer/json/JsonObject.java
Normal file
377
core/src/main/java/eu/jonahbauer/json/JsonObject.java
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
package eu.jonahbauer.json;
|
||||||
|
|
||||||
|
import eu.jonahbauer.json.exceptions.JsonConversionException;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java representation of a JSON object.
|
||||||
|
* @param entries the object's entries
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public record JsonObject(@NotNull Map<@NotNull String, @Nullable JsonValue> entries) implements JsonValue, Map<@NotNull String, @Nullable JsonValue> {
|
||||||
|
public static final @NotNull JsonObject EMPTY = new JsonObject(Map.of());
|
||||||
|
|
||||||
|
public JsonObject {
|
||||||
|
Objects.requireNonNull(entries, "entries");
|
||||||
|
entries = Util.defensiveCopy(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON object containing one mapping.
|
||||||
|
* @param k1 the key
|
||||||
|
* @param v1 the value
|
||||||
|
* @return a new JSON object containing the specified mapping
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonObject of(
|
||||||
|
@NotNull String k1, @Nullable JsonValue v1
|
||||||
|
) {
|
||||||
|
var map = new LinkedHashMap<String, JsonValue>();
|
||||||
|
map.put(Objects.requireNonNull(k1), v1);
|
||||||
|
return new JsonObject(Util.trusted(Collections.unmodifiableSequencedMap(map)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON object containing two mapping.
|
||||||
|
* @param k1 the first key
|
||||||
|
* @param v1 the first value
|
||||||
|
* @param k2 the second key
|
||||||
|
* @param v2 the second value
|
||||||
|
* @return a new JSON object containing the specified mappings
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonObject of(
|
||||||
|
@NotNull String k1, @Nullable JsonValue v1,
|
||||||
|
@NotNull String k2, @Nullable JsonValue v2
|
||||||
|
) {
|
||||||
|
var map = new LinkedHashMap<String, JsonValue>();
|
||||||
|
map.put(Objects.requireNonNull(k1), v1);
|
||||||
|
map.put(Objects.requireNonNull(k2), v2);
|
||||||
|
return new JsonObject(Util.trusted(Collections.unmodifiableSequencedMap(map)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON object containing three mapping.
|
||||||
|
* @param k1 the first key
|
||||||
|
* @param v1 the first value
|
||||||
|
* @param k2 the second key
|
||||||
|
* @param v2 the second value
|
||||||
|
* @param k3 the third key
|
||||||
|
* @param v3 the third value
|
||||||
|
* @return a new JSON object containing the specified mappings
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonObject of(
|
||||||
|
@NotNull String k1, @Nullable JsonValue v1,
|
||||||
|
@NotNull String k2, @Nullable JsonValue v2,
|
||||||
|
@NotNull String k3, @Nullable JsonValue v3
|
||||||
|
) {
|
||||||
|
var map = new LinkedHashMap<String, JsonValue>();
|
||||||
|
map.put(Objects.requireNonNull(k1), v1);
|
||||||
|
map.put(Objects.requireNonNull(k2), v2);
|
||||||
|
map.put(Objects.requireNonNull(k3), v3);
|
||||||
|
return new JsonObject(Util.trusted(Collections.unmodifiableSequencedMap(map)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a JSON object containing four mapping.
|
||||||
|
* @param k1 the first key
|
||||||
|
* @param v1 the first value
|
||||||
|
* @param k2 the second key
|
||||||
|
* @param v2 the second value
|
||||||
|
* @param k3 the third key
|
||||||
|
* @param v3 the third value
|
||||||
|
* @param k4 the fourth key
|
||||||
|
* @param v4 the fourth value
|
||||||
|
* @return a new JSON object containing the specified mappings
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonObject of(
|
||||||
|
@NotNull String k1, @Nullable JsonValue v1,
|
||||||
|
@NotNull String k2, @Nullable JsonValue v2,
|
||||||
|
@NotNull String k3, @Nullable JsonValue v3,
|
||||||
|
@NotNull String k4, @Nullable JsonValue v4
|
||||||
|
) {
|
||||||
|
var map = new LinkedHashMap<String, JsonValue>();
|
||||||
|
map.put(Objects.requireNonNull(k1), v1);
|
||||||
|
map.put(Objects.requireNonNull(k2), v2);
|
||||||
|
map.put(Objects.requireNonNull(k3), v3);
|
||||||
|
map.put(Objects.requireNonNull(k4), v4);
|
||||||
|
return new JsonObject(Util.trusted(Collections.unmodifiableSequencedMap(map)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a JSON object from the given map, using {@link JsonValue#valueOf(Object)} to convert the values to
|
||||||
|
* {@link JsonValue}s. The keys are expected to be instances of {@link CharSequence}.
|
||||||
|
* @param map a map
|
||||||
|
* @return a new JSON object
|
||||||
|
* @throws JsonConversionException if the given map or its entries cannot be converted to json
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonObject valueOf(@Nullable Map<?, ?> map) {
|
||||||
|
if (map == null) return null;
|
||||||
|
if (map instanceof JsonObject json) return json;
|
||||||
|
|
||||||
|
var out = new LinkedHashMap<String, JsonValue>();
|
||||||
|
map.forEach((key, value) -> out.put(keyOf(key), JsonValue.valueOf(value)));
|
||||||
|
return new JsonObject(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull String keyOf(@Nullable Object object) {
|
||||||
|
return switch (object) {
|
||||||
|
case CharSequence chars -> chars.toString();
|
||||||
|
case null -> throw new JsonConversionException("cannot use null as json key");
|
||||||
|
default -> throw new JsonConversionException("cannot convert object of type " + object.getClass() + " to json key");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//<editor-fold desc="Map" defaultstate="collapsed">
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return entries.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return entries.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(Object key) {
|
||||||
|
Objects.requireNonNull(key, "key");
|
||||||
|
return entries.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean containsValue(Object value) {
|
||||||
|
return entries.containsValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable JsonValue get(Object key) {
|
||||||
|
Objects.requireNonNull(key, "key");
|
||||||
|
return entries.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable JsonValue put(@NotNull String key, @Nullable JsonValue value) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable JsonValue remove(Object key) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putAll(@NotNull Map<? extends @NotNull String, ? extends @Nullable JsonValue> m) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<@NotNull String> keySet() {
|
||||||
|
return entries.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Collection<@Nullable JsonValue> values() {
|
||||||
|
return entries.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull Set<Entry<@NotNull String, @Nullable JsonValue>> entrySet() {
|
||||||
|
return entries.entrySet();
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold desc="get...(String key)" defaultstate="collapsed">
|
||||||
|
/**
|
||||||
|
* {@return the value to which the specified key is mapped, or <code>null</code> if this object contains no mapping for the key}
|
||||||
|
* @throws ClassCastException if the value is not an instance of {@link JsonString}
|
||||||
|
* @throws NullPointerException if there is no mapping for the key or the key is mapped to {@code null}
|
||||||
|
*/
|
||||||
|
public @NotNull JsonString getString(@NotNull String key) {
|
||||||
|
return get(key, JsonString.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the value to which the specified key is mapped, or <code>null</code> if this object contains no mapping for the key}
|
||||||
|
* @throws ClassCastException if the value is not an instance of {@link JsonNumber}
|
||||||
|
* @throws NullPointerException if there is no mapping for the key or the key is mapped to {@code null}
|
||||||
|
*/
|
||||||
|
public @NotNull JsonNumber getNumber(@NotNull String key) {
|
||||||
|
return get(key, JsonNumber.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the value to which the specified key is mapped, or <code>null</code> if this object contains no mapping for the key}
|
||||||
|
* @throws ClassCastException if the value is not an instance of {@link JsonBoolean}
|
||||||
|
* @throws NullPointerException if there is no mapping for the key or the key is mapped to {@code null}
|
||||||
|
*/
|
||||||
|
public @NotNull JsonBoolean getBoolean(@NotNull String key) {
|
||||||
|
return get(key, JsonBoolean.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the value to which the specified key is mapped, or <code>null</code> if this object contains no mapping for the key}
|
||||||
|
* @throws ClassCastException if the value is not an instance of {@link JsonArray}
|
||||||
|
* @throws NullPointerException if there is no mapping for the key or the key is mapped to {@code null}
|
||||||
|
*/
|
||||||
|
public @NotNull JsonArray getArray(@NotNull String key) {
|
||||||
|
return get(key, JsonArray.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the value to which the specified key is mapped, or <code>null</code> if this object contains no mapping for the key}
|
||||||
|
* @throws ClassCastException if the value is not an instance of {@link JsonObject}
|
||||||
|
* @throws NullPointerException if there is no mapping for the key or the key is mapped to {@code null}
|
||||||
|
*/
|
||||||
|
public @NotNull JsonObject getObject(@NotNull String key) {
|
||||||
|
return get(key, JsonObject.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends JsonValue> @NotNull T get(@NotNull String key, @NotNull Class<T> type) {
|
||||||
|
var value = entries().get(key);
|
||||||
|
if (value == null) {
|
||||||
|
if (entries().containsKey(key)) {
|
||||||
|
throw new NullPointerException("Key " + key + " is mapped to null.");
|
||||||
|
} else {
|
||||||
|
throw new NullPointerException("No mapping for key " + key);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return type.cast(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
//<editor-fold desc="get...OrDefault(String key, ...)" defaultstate="collapsed">
|
||||||
|
// getStringOrDefault(String, JsonString) omitted because JsonString implements CharSequence
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or
|
||||||
|
* {@link JsonString#valueOf(CharSequence) JsonString.valueOf(defaultValue)} if this object contains no mapping for
|
||||||
|
* the key or the key is mapped to a value that is not an instance of {@link JsonString}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonString getStringOrDefault(@NotNull String key, @Nullable CharSequence defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonString.class, JsonString::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or {@code defaultValue} if this object contains no mapping
|
||||||
|
* for the key or the key is mapped to a value that is not an instance of {@link JsonNumber}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonNumber getNumberOrDefault(@NotNull String key, @Nullable JsonNumber defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonNumber.class, Function.identity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or
|
||||||
|
* {@link JsonNumber#valueOf(Number) JsonNumber.valueOf(defaultValue)} if this object contains no mapping for the
|
||||||
|
* key or the key is mapped to a value that is not an instance of {@link JsonNumber}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonNumber getNumberOrDefault(@NotNull String key, @Nullable Number defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonNumber.class, JsonNumber::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or {@code defaultValue} if this object contains no mapping
|
||||||
|
* for the key or the key is mapped to a value that is not an instance of {@link JsonBoolean}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonBoolean getBooleanOrDefault(@NotNull String key, @Nullable JsonBoolean defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonBoolean.class, Function.identity());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or
|
||||||
|
* {@link JsonBoolean#valueOf(Boolean) JsonBoolean.valueOf(defaultValue)} if this object contains no mapping
|
||||||
|
* for the key or the key is mapped to a value that is not an instance of {@link JsonBoolean}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonBoolean getBooleanOrDefault(@NotNull String key, @Nullable Boolean defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonBoolean.class, JsonBoolean::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// getArrayOrDefault(String, JsonArray) omitted because JsonArray implements List<?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or
|
||||||
|
* {@link JsonArray#valueOf(List) JsonArray.valueOf(defaultValue)} if this object contains no mapping for
|
||||||
|
* the key or the key is mapped to a value that is not an instance of {@link JsonArray}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonArray getArrayOrDefault(@NotNull String key, @Nullable List<?> defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonArray.class, JsonArray::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or
|
||||||
|
* {@link JsonArray#valueOf(Object...) JsonArray.valueOf(defaultValue)} if this object contains no mapping for the
|
||||||
|
* key or the key is mapped to a value that is not an instance of {@link JsonArray}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonArray getArrayOrDefault(@NotNull String key, @Nullable Object @Nullable... defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonArray.class, JsonArray::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// getObjectOrDefault(String, JsonObject) omitted because JsonObject implements Map<?, ?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value to which the specified key is mapped, or
|
||||||
|
* {@link JsonObject#valueOf(Map) JsonObject.valueOf(defaultValue)} if this object contains no mapping for the key
|
||||||
|
* or the key is mapped to a value that is not an instance of {@link JsonObject}.
|
||||||
|
* @return the value to which the specified key is mapped falling back to the default value
|
||||||
|
*/
|
||||||
|
public @Nullable JsonObject getObjectOrDefault(@NotNull String key, @Nullable Map<?, ?> defaultValue) {
|
||||||
|
return getOrDefault(key, defaultValue, JsonObject.class, JsonObject::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends JsonValue, S> @Nullable T getOrDefault(@NotNull String key, @Nullable S defaultValue, @NotNull Class<T> type, @NotNull Function<S, T> converter) {
|
||||||
|
var value = entries().get(key);
|
||||||
|
if (type.isInstance(value)) {
|
||||||
|
return type.cast(value);
|
||||||
|
} else {
|
||||||
|
return converter.apply(defaultValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
StringJoiner out = new StringJoiner(",", "{", "}");
|
||||||
|
entries.forEach((key, value) -> out.add(JsonString.quote(key) + ":" + JsonValue.toJsonString(value)));
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toPrettyJsonString() {
|
||||||
|
StringJoiner out = new StringJoiner(",\n ", "{\n ", "\n}");
|
||||||
|
entries.forEach((key, value) -> out.add(JsonString.quote(key) + ": " + indent(JsonValue.toPrettyJsonString(value))));
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull String indent(@NotNull String string) {
|
||||||
|
if (string.isEmpty()) return "";
|
||||||
|
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
|
||||||
|
Iterator<String> it = string.lines().iterator();
|
||||||
|
out.append(it.next());
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
String next = it.next();
|
||||||
|
out.append('\n').append(it.hasNext() ? " " : " ").append(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
}
|
127
core/src/main/java/eu/jonahbauer/json/JsonString.java
Normal file
127
core/src/main/java/eu/jonahbauer/json/JsonString.java
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package eu.jonahbauer.json;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public record JsonString(@NotNull String value) implements JsonValue, CharSequence {
|
||||||
|
public static final @NotNull JsonString EMPTY = new JsonString("");
|
||||||
|
|
||||||
|
public JsonString {
|
||||||
|
Objects.requireNonNull(value, "value");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given character to a JSON string.
|
||||||
|
* @param chr a character
|
||||||
|
* @return a new JSON string
|
||||||
|
*/
|
||||||
|
public static @NotNull JsonString valueOf(char chr) {
|
||||||
|
return new JsonString(String.valueOf(chr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given character to a JSON string.
|
||||||
|
* @param chr a character
|
||||||
|
* @return a new JSON string
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonString valueOf(@Nullable Character chr) {
|
||||||
|
return chr == null ? null : new JsonString(String.valueOf(chr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given string to a JSON string.
|
||||||
|
* @param chars a string
|
||||||
|
* @return a new JSON string
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
public static @Nullable JsonString valueOf(@Nullable CharSequence chars) {
|
||||||
|
return switch (chars) {
|
||||||
|
case JsonString json -> json;
|
||||||
|
case null -> null;
|
||||||
|
default -> {
|
||||||
|
@SuppressWarnings("java:S2259")
|
||||||
|
var result = new JsonString(chars.toString());
|
||||||
|
yield result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quotes the given {@link String} and encodes all invalid characters as an escape sequence.
|
||||||
|
* @param value a string value
|
||||||
|
* @return a JSON representation of the given {@code value}
|
||||||
|
*/
|
||||||
|
public static @NotNull String quote(@NotNull String value) {
|
||||||
|
StringBuilder out = new StringBuilder(value.length() + 2);
|
||||||
|
out.append('"');
|
||||||
|
for (int i = 0, length = value.length(); i < length; i++) {
|
||||||
|
char chr = value.charAt(i);
|
||||||
|
switch (chr) {
|
||||||
|
case '"' -> out.append("\\\"");
|
||||||
|
case '\\' -> out.append("\\\\");
|
||||||
|
case '\b' -> out.append("\\b");
|
||||||
|
case '\f' -> out.append("\\f");
|
||||||
|
case '\n' -> out.append("\\n");
|
||||||
|
case '\r' -> out.append("\\r");
|
||||||
|
case '\t' -> out.append("\\t");
|
||||||
|
default -> {
|
||||||
|
if (chr < 32) {
|
||||||
|
out.append("\\u%04x".formatted((int) chr));
|
||||||
|
} else {
|
||||||
|
out.append(chr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.append('"');
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//<editor-fold desc="CharSequence" defaultstate="collapsed">
|
||||||
|
@Override
|
||||||
|
public int length() {
|
||||||
|
return value.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public char charAt(int index) {
|
||||||
|
return value.charAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull JsonString subSequence(int start, int end) {
|
||||||
|
return new JsonString(value.substring(start, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return value.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IntStream chars() {
|
||||||
|
return value.chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull IntStream codePoints() {
|
||||||
|
return value.codePoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toString() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
//</editor-fold>
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String toJsonString() {
|
||||||
|
return quote(value());
|
||||||
|
}
|
||||||
|
}
|
83
core/src/main/java/eu/jonahbauer/json/JsonValue.java
Normal file
83
core/src/main/java/eu/jonahbauer/json/JsonValue.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package eu.jonahbauer.json;
|
||||||
|
|
||||||
|
import eu.jonahbauer.json.exceptions.JsonConversionException;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public sealed interface JsonValue extends Serializable permits JsonObject, JsonArray, JsonBoolean, JsonNumber, JsonString {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the JSON representation of this value}
|
||||||
|
*/
|
||||||
|
default @NotNull String toJsonString() {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return a prettified JSON representation of this value}
|
||||||
|
*/
|
||||||
|
default @NotNull String toPrettyJsonString() {
|
||||||
|
return toJsonString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the JSON representation of the given value}
|
||||||
|
* @param value a {@link JsonValue} (possibly {@code null})
|
||||||
|
*/
|
||||||
|
static @NotNull String toJsonString(@Nullable JsonValue value) {
|
||||||
|
return value == null ? "null" : value.toJsonString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@return the prettified JSON representation of the given value}
|
||||||
|
* @param value a {@link JsonValue} (possibly {@code null})
|
||||||
|
*/
|
||||||
|
static @NotNull String toPrettyJsonString(@Nullable JsonValue value) {
|
||||||
|
return value == null ? "null" : value.toPrettyJsonString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an object to a JSON value:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@link JsonValue}s and {@code null} are returned as is</li>
|
||||||
|
* <li>{@link Boolean}s are converted with {@link JsonBoolean#valueOf(Boolean)}</li>
|
||||||
|
* <li>{@link Number}s are converted with {@link JsonNumber#valueOf(Number)}</li>
|
||||||
|
* <li>{@link Character}s are converted with {@link JsonString#valueOf(Character)}</li>
|
||||||
|
* <li>{@link CharSequence}s are converted with {@link JsonString#valueOf(CharSequence)}</li>
|
||||||
|
* <li>{@link List}s are converted with {@link JsonArray#valueOf(List)}</li>
|
||||||
|
* <li>arrays are converted with the respective overload of {@link JsonArray#valueOf(Object...)}</li>
|
||||||
|
* <li>{@link Map}s are converted with {@link JsonObject#valueOf(Map)}</li>
|
||||||
|
* </ul>
|
||||||
|
* @param object an object
|
||||||
|
* @return a {@link JsonValue} representing the object
|
||||||
|
* @throws JsonConversionException if the object cannot be converted to a {@link JsonValue}
|
||||||
|
*/
|
||||||
|
@Contract("null -> null; !null -> !null")
|
||||||
|
static @Nullable JsonValue valueOf(@Nullable Object object) {
|
||||||
|
return switch (object) {
|
||||||
|
case JsonValue json -> json;
|
||||||
|
case Boolean bool -> JsonBoolean.valueOf(bool);
|
||||||
|
case Number number -> JsonNumber.valueOf(number);
|
||||||
|
case Character chr -> JsonString.valueOf(String.valueOf(chr));
|
||||||
|
case CharSequence chars -> JsonString.valueOf(chars);
|
||||||
|
case List<?> list -> JsonArray.valueOf(list);
|
||||||
|
case Object[] array -> JsonArray.valueOf(array);
|
||||||
|
case boolean[] array -> JsonArray.valueOf(array);
|
||||||
|
case byte[] array -> JsonArray.valueOf(array);
|
||||||
|
case short[] array -> JsonArray.valueOf(array);
|
||||||
|
case char[] array -> JsonArray.valueOf(array);
|
||||||
|
case int[] array -> JsonArray.valueOf(array);
|
||||||
|
case long[] array -> JsonArray.valueOf(array);
|
||||||
|
case float[] array -> JsonArray.valueOf(array);
|
||||||
|
case double[] array -> JsonArray.valueOf(array);
|
||||||
|
case Map<?, ?> map -> JsonObject.valueOf(map);
|
||||||
|
case null -> null;
|
||||||
|
default -> throw new JsonConversionException("cannot convert object of type " + object.getClass() + " to json value");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
69
core/src/main/java/eu/jonahbauer/json/Util.java
Normal file
69
core/src/main/java/eu/jonahbauer/json/Util.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package eu.jonahbauer.json;
|
||||||
|
|
||||||
|
import lombok.experimental.Delegate;
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@UtilityClass
|
||||||
|
class Util {
|
||||||
|
private static final @NotNull Class<?> LIST_1_2 = List.of(1).getClass();
|
||||||
|
private static final @NotNull Class<?> LIST_N = List.of(1, 2, 3).getClass();
|
||||||
|
private static final @NotNull Class<?> SUB_LIST = List.of(1, 2, 3).subList(0, 2).getClass();
|
||||||
|
private static final @NotNull Class<?> MAP_1 = Map.of(1, 2).getClass();
|
||||||
|
private static final @NotNull Class<?> MAP_N = Map.of(1, 2, 3, 4).getClass();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a defensive copy of the given list unless it is known to be an immutable list.
|
||||||
|
*/
|
||||||
|
public static <T> @NotNull List<T> defensiveCopy(@NotNull List<T> list) {
|
||||||
|
if (LIST_1_2.isInstance(list) || LIST_N.isInstance(list) || SUB_LIST.isInstance(list)) {
|
||||||
|
return list;
|
||||||
|
} else if (list instanceof TrustedList<T>(var delegate)) {
|
||||||
|
return delegate;
|
||||||
|
} else {
|
||||||
|
return list.stream().toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a defensive copy of the given map unless it is known to be an immutable map.
|
||||||
|
* If the given map implements {@link SequencedMap} as will the returned one.
|
||||||
|
*/
|
||||||
|
public static <K, V> @NotNull Map<K, V> defensiveCopy(@NotNull Map<@NotNull K, V> map) {
|
||||||
|
if (MAP_1.isInstance(map) || MAP_N.isInstance(map)) {
|
||||||
|
return map;
|
||||||
|
} else if (map instanceof TrustedMap<K, V>(var delegate)) {
|
||||||
|
return delegate;
|
||||||
|
} else if (map instanceof SequencedMap<K,V> sequenced) {
|
||||||
|
var out = new LinkedHashMap<K, V>();
|
||||||
|
sequenced.forEach((key, value) -> out.put(Objects.requireNonNull(key, "key"), value));
|
||||||
|
return Collections.unmodifiableSequencedMap(out);
|
||||||
|
} else {
|
||||||
|
var out = new HashMap<K, V>();
|
||||||
|
map.forEach((key, value) -> out.put(Objects.requireNonNull(key, "key"), value));
|
||||||
|
return Collections.unmodifiableMap(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list that will be assumed immutable when given to {@link #defensiveCopy(List)}.
|
||||||
|
* {@return a list that will be assumed immutable}
|
||||||
|
*/
|
||||||
|
public static <T> @NotNull List<T> trusted(@NotNull List<T> list) {
|
||||||
|
return new TrustedList<>(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a map that will be assumed immutable when given to {@link #defensiveCopy(Map)}.
|
||||||
|
* {@return a map that will be assumed immutable}
|
||||||
|
*/
|
||||||
|
public static <K, V> @NotNull Map<K, V> trusted(@NotNull Map<@NotNull K, V> map) {
|
||||||
|
return new TrustedMap<>(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
private record TrustedList<T>(@Delegate @NotNull List<T> delegate) implements List<T> {}
|
||||||
|
|
||||||
|
private record TrustedMap<K, V>(@Delegate @NotNull Map<K, V> delegate) implements Map<K, V> {}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package eu.jonahbauer.json.exceptions;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception that indicates problems with conversion between java objects and json.
|
||||||
|
*/
|
||||||
|
public class JsonConversionException extends JsonProcessingException {
|
||||||
|
public JsonConversionException(@NotNull String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonConversionException(@NotNull String message, @NotNull Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package eu.jonahbauer.json.exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent class for exceptions related to json processing.
|
||||||
|
*/
|
||||||
|
public abstract class JsonProcessingException extends RuntimeException {
|
||||||
|
public JsonProcessingException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonProcessingException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
7
core/src/main/java/module-info.java
Normal file
7
core/src/main/java/module-info.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module eu.jonahbauer.json {
|
||||||
|
requires static lombok;
|
||||||
|
requires static org.jetbrains.annotations;
|
||||||
|
|
||||||
|
exports eu.jonahbauer.json;
|
||||||
|
exports eu.jonahbauer.json.exceptions;
|
||||||
|
}
|
7
gradle/libs.versions.toml
Normal file
7
gradle/libs.versions.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[versions]
|
||||||
|
annotations = "24.1.0"
|
||||||
|
lombok = "1.18.32"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
annotations = { module = "org.jetbrains:annotations", version.ref = "annotations" }
|
||||||
|
lombok = { module = "org.projectlombok:lombok", version.ref = "lombok" }
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
249
gradlew
vendored
Normal file
249
gradlew
vendored
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
92
gradlew.bat
vendored
Normal file
92
gradlew.bat
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
11
settings.gradle.kts
Normal file
11
settings.gradle.kts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
@Suppress("UnstableApiUsage")
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.name = "json"
|
||||||
|
include("core")
|
Loading…
x
Reference in New Issue
Block a user