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

org.kiwiproject.jackson.KiwiJacksonDataFormats Maven / Gradle / Ivy

package org.kiwiproject.jackson;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.format.DataFormatDetector;
import com.fasterxml.jackson.dataformat.xml.XmlFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Optional;

/**
 * Static utilities for easily performing data format detection on String values. Currently this class supports
 * detection of JSON, XML, and YAML assuming the YAML begins with the explicit document start marker ("---").
 * 

* NOTE: This relies entirely on jackson's data format detection!!! You will also need to ensure that the * jackson-core, jackson-dataformat-xml, jackson-dataformat-yaml dependencies are present at runtime. *

* WARNING: Before using, please make sure you understand how Jackson actually does its detection. Hint: it's not * magic, and may not be as robust as you might like. For example the YAML detector will only report YAML if the * content starts with the formal YAML preamble "---". Use the "@see" links below for links to the various Jackson * classes that perform data format detection. The main class is {@link DataFormatDetector}, to which you supply * one or more detectors, which are {@link JsonFactory} and its subclasses. * * @see DataFormatDetector * @see JsonFactory * @see XmlFactory * @see YAMLFactory * @see Charset#defaultCharset() */ @UtilityClass @Slf4j public class KiwiJacksonDataFormats { private static final Charset DEFAULT_CHARSET = Charset.defaultCharset(); /** * We currently support JSON, XML, and YAML. */ private static final DataFormatDetector DEFAULT_FORMAT_DETECTOR = new DataFormatDetector(new JsonFactory(), new XmlFactory(), new YAMLFactory()); /** * Is the given text JSON using the default {@link Charset}? * * @param text the String value to check * @return {@code true} if text is JSON; {@code false} otherwise */ public static boolean isJson(String text) { return isJson(text, DEFAULT_CHARSET); } /** * Is the given text JSON using UTF-8 {@link Charset}? * * @param text the String value to check * @return {@code true} if text is JSON; {@code false} otherwise */ public static boolean isJsonUtf8(String text) { return isJson(text, UTF_8); } /** * Is the given text JSON using the given {@link Charset}? * * @param text the String value to check * @param charset the character set to use * @return {@code true} if text is JSON; {@code false} otherwise */ public static boolean isJson(String text, Charset charset) { return isFormat(JacksonDataFormat.JSON, text, charset); } /** * Is the given text XML using the default {@link Charset}? * * @param text the String value to check * @return {@code true} if text is XML; {@code false} otherwise */ public static boolean isXml(String text) { return isXml(text, DEFAULT_CHARSET); } /** * Is the given text XML using UTF-8 {@link Charset}? * * @param text the String value to check * @return {@code true} if text is XML; {@code false} otherwise */ public static boolean isXmlUtf8(String text) { return isXml(text, UTF_8); } /** * Is the given text XML using the given {@link Charset}? * * @param text the String value to check * @param charset the character set to use * @return {@code true} if text is XML; {@code false} otherwise */ public static boolean isXml(String text, Charset charset) { return isFormat(JacksonDataFormat.XML, text, charset); } /** * Is the given text YAML using the default {@link Charset}? * * @param text the String value to check * @return {@code true} if text is YAML; {@code false} otherwise * @implNote Jackson does NOT consider the content YAML without "---" at the top of the file! */ public static boolean isYaml(String text) { return isYaml(text, DEFAULT_CHARSET); } /** * Is the given text YAML using UTF-8 {@link Charset}? * * @param text the String value to check * @return {@code true} if text is YAML; {@code false} otherwise * @implNote Jackson does NOT consider the content YAML without "---" at the top of the file! */ public static boolean isYamlUtf8(String text) { return isYaml(text, UTF_8); } /** * Is the given text YAML using the given {@link Charset}? * * @param text the String value to check * @param charset the character set to use * @return {@code true} if text is YAML; {@code false} otherwise * @implNote Jackson does NOT consider the content YAML without "---" at the top of the file! */ public static boolean isYaml(String text, Charset charset) { return isFormat(JacksonDataFormat.YAML, text, charset); } /** * Does the given text, using the given {@link Charset}, have data format {@code matchFormat}. * * @param matchFormat the format to match against * @param text the String value to check * @param charset the character set to use * @return {@code true} if text is equal to {@code matchFormat}; {@code false} otherwise */ public static boolean isFormat(JacksonDataFormat matchFormat, String text, Charset charset) { return detectFormat(text, charset) .filter(dataFormat -> dataFormat == matchFormat) .isPresent(); } /** * Detect data format of given text using the default {@link Charset}. * * @param text the String value to check * @return Optional containing detected format, or empty Optional if format was not * detected or not supported */ public static Optional detectFormat(String text) { return detectFormat(text, DEFAULT_CHARSET); } /** * Detect data format of given text using UTF-8 {@link Charset}. * * @param text the String value to check * @return Optional containing detected format, or empty Optional if format was not * detected or not supported */ public static Optional detectFormatUtf8(String text) { return detectFormat(text, UTF_8); } /** * Detect data format of given text using the given {@link Charset}. * * @param text the String value to check * @param charset the character set to use * @return Optional containing detected format, or empty Optional if format was not * detected or not supported */ public static Optional detectFormat(String text, Charset charset) { var optionalFormatName = detectFormat(text, charset, DEFAULT_FORMAT_DETECTOR); return optionalFormatName .map(JacksonDataFormat::from) .or(Optional::empty); } /** * Detect data format of given text using given {@link Charset} and {@link DataFormatDetector}. *

* This method is an "escape hatch"; it allows detection of formats not supported in {@link JacksonDataFormat} * since it accepts a {@link DataFormatDetector} and it returns a String. Thus, since the caller supplies its own * custom {@link DataFormatDetector}, the formats that are supported are dictated entirely by that caller. And * because it returns a String, it is not limited to the formats defined in the {@link JacksonDataFormat} enum. * * @param text the String value to check * @param charset the character set to use * @param detector the format detector to use * @return Optional containing detected format name, or empty Optional if format was not * detected or not supported by the supplied {@link DataFormatDetector} */ public static Optional detectFormat(String text, Charset charset, DataFormatDetector detector) { try { var bytes = text.getBytes(charset); var formatMatcher = detector.findFormat(bytes); if (formatMatcher.hasMatch()) { return Optional.of(formatMatcher.getMatchedFormatName()); } } catch (IOException e) { LOG.debug("Error finding data format", e); } return Optional.empty(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy