All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xjs.serialization.JsonContext Maven / Gradle / Ivy

There is a newer version: 0.36
Show newest version
package xjs.serialization;

import xjs.comments.CommentStyle;
import xjs.core.Json;
import xjs.core.JsonValue;
import xjs.exception.SyntaxException;
import xjs.serialization.parser.JsonParser;
import xjs.serialization.parser.ParsingFunction;
import xjs.serialization.parser.XjsParser;
import xjs.serialization.writer.JsonWriter;
import xjs.serialization.writer.JsonWriterOptions;
import xjs.serialization.writer.WritingFunction;
import xjs.serialization.writer.XjsWriter;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A collection of settings and serializers for automatic parsing and writing.
 *
 * 

This context may be used to configure the behavior of this library. For * example, to configure the default comment style or newline character used * by all provided serializers: * *

{@code
 *   JsonContext.setDefaultCommentStyle(CommentStyle.HASH);
 *   JsonContext.setEol("\n");
 * }
* *

Or the formatting options used by all default serializers: * *

{@code
 *   JsonContext.setDefaultFormatting(
 *     new JsonWriterOptions()
 *       .setIndent("    ")
 *       .setMaxSpacing(3))
 * }
* *

In addition, the context is provided as a way to configure the automatic * format selection of {@link Json} and {@link JsonValue}: * *

{@code
 *   JsonContext.addParser("yaml", file -> new MyYamlParser(file).parse());
 *   JsonContext.addWriter("yaml" (w, v, o) -> new MyYamlWriter(w, o).write(v));
 * }
*/ public class JsonContext { private static final Map PARSERS = new ConcurrentHashMap<>(); private static final Map WRITERS = new ConcurrentHashMap<>(); private static final Map ALIASES = new ConcurrentHashMap<>(); private static final ParsingFunction DEFAULT_PARSER = ParsingFunction.fromParser(XjsParser::new); private static final WritingFunction DEFAULT_WRITER = WritingFunction.fromWriter(XjsWriter::new); private static volatile String eol = System.lineSeparator(); private static volatile CommentStyle defaultCommentStyle = CommentStyle.LINE; private static volatile JsonWriterOptions defaultFormatting = new JsonWriterOptions(); /** * Indicates whether the xjs-compat module is provided, enabling support for * Hjson, JSON-C, YAML, and other foreign serializers. */ public static final boolean COMPAT_AVAILABLE; /** * Indicates whether the xjs-jel module is provided, enabling support for JEL * expressions and data processing. */ public static final boolean JEL_AVAILABLE; /** * Indicates whether the xjs-transform module is provided, enabling support for * data transforms and formatters. */ public static final boolean TRANSFORM_AVAILABLE; /** * Adds or replaces a parser for the given format. * *

Note that parsing functions would ideally not get reused for multiple formats. * For this purpose, use {@link #registerAlias}. * * @param format The file extension corresponding to this parser. * @param parser A function of {@link File} -> {@link JsonValue} throwing IOException */ public static void addParser(final String format, final ParsingFunction parser) { PARSERS.put(format.toLowerCase(), parser); } /** * Adds or replaces a writer for the given format. * *

Note that writing functions would ideally not get reused for multiple formats. * For this purpose, use {@link #registerAlias}. * * @param format The file extension corresponding to the parser. * @param writer A consumer of ({@link Writer}, {@link JsonValue}, {@link JsonWriterOptions}) */ public static void addWriter(final String format, final WritingFunction writer) { WRITERS.put(format.toLowerCase(), writer); } /** * Registers an alias for some other format to the context. * *

For example, to register yml as an alias of yaml: * *

{@code
     *   JsonContext.registerAlias("yml", "yaml");
     * }
* * @param alias An alias for the expected format. * @param format The expected format being configured. */ public static void registerAlias(final String alias, final String format) { ALIASES.put(alias.toLowerCase(), format.toLowerCase()); } /** * Gets the default newline character configured the provided serializers. * * @return The default newline character, usually {@link System#lineSeparator()} */ public static synchronized String getEol() { return eol; } /** * Sets the default newline character configured for the provided serializers. * * @param eol The default newline character, e.g. \n */ public static synchronized void setEol(final String eol) { JsonContext.eol = eol; } /** * Gets the default newline character used by {@link JsonValue#setComment(String)}. * * @return The configured {@link CommentStyle}. */ public static synchronized CommentStyle getDefaultCommentStyle() { return defaultCommentStyle; } /** * Sets the default newline character used by {@link JsonValue#setComment(String)}. * * @param style The configured {@link CommentStyle}. */ public static synchronized void setDefaultCommentStyle(final CommentStyle style) { defaultCommentStyle = style; } /** * Gets the default formatting options used by the provided serializers. * * @return The default {@link JsonWriterOptions}. */ public static synchronized JsonWriterOptions getDefaultFormatting() { return new JsonWriterOptions(defaultFormatting); } /** * Sets the default formatting options used by the provided serializers. * * @param options The default {@link JsonWriterOptions}. */ public static synchronized void setDefaultFormatting(final JsonWriterOptions options) { defaultFormatting = options; } /** * Indicates whether the given file is extended with a known format or alias. * * @param file The file being tested. * @return true, if the extension is recognized by the context. */ public static boolean isKnownFormat(final File file) { final String ext = getExtension(file); return PARSERS.containsKey(ext) || ALIASES.containsKey(ext); } /** * Parses the given file automatically based on its extension. * *

This method is the delegate of {@link Json#parse(File)}. * * @param file The file being parsed as some kind of JSON file or superset. * @return The {@link JsonValue} represented by the file. * @throws IOException If the underlying {@link FileReader} throws an exception. * @throws SyntaxException If the contents of the file are syntactically invalid. */ public static JsonValue autoParse(final File file) throws IOException { return PARSERS.getOrDefault(getFormat(file), DEFAULT_PARSER).parse(file); } /** * Writes the given file automatically based on its extension. * *

This method is the delegate of {@link JsonValue#write(File)}. * * @param file The file being written as some kind of JSON file or superset. * @param value The {@link JsonValue} to be represented by the file. * @throws IOException If the underlying {@link FileWriter} throws an exception. */ public static void autoWrite(final File file, final JsonValue value) throws IOException { WRITERS.getOrDefault(getFormat(file), DEFAULT_WRITER).write(file, value, defaultFormatting); } private static String getFormat(final File file) { final String ext = getExtension(file); return ALIASES.getOrDefault(ext, ext); } private static String getExtension(final File file) { final int index = file.getName().lastIndexOf('.'); return index < 0 ? "xjs" : file.getName().substring(index + 1).toLowerCase(); } static { PARSERS.put("json", ParsingFunction.fromParser(JsonParser::new)); PARSERS.put("xjs", DEFAULT_PARSER); WRITERS.put("json", WritingFunction.fromWriter(JsonWriter::new)); WRITERS.put("xjs", DEFAULT_WRITER); COMPAT_AVAILABLE = isClassAvailable("xjs.serialization.XjsCompat"); JEL_AVAILABLE = isClassAvailable("xjs.jel.JelContext"); TRANSFORM_AVAILABLE = isClassAvailable("xjs.transform.JsonTransformer"); } private static boolean isClassAvailable(final String name) { try { Class.forName(name); return true; } catch (final ClassNotFoundException ignored) {} return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy