From 03ac60394af8f0a531a45979e7c17d8322228ad7 Mon Sep 17 00:00:00 2001 From: Christopher Cudennec Date: Fri, 14 Feb 2025 11:12:30 +0100 Subject: [PATCH 1/2] add Spotless + Maven wrapper --- .github/workflows/json-smart-formatting.yml | 31 +++ .github/workflows/json-smart-unit-tests.yml | 6 +- .../.mvn/wrapper/maven-wrapper.properties | 19 ++ accessors-smart/mvnw | 259 ++++++++++++++++++ accessors-smart/mvnw.cmd | 149 ++++++++++ accessors-smart/pom.xml | 15 + .../.mvn/wrapper/maven-wrapper.properties | 19 ++ json-smart-action/mvnw | 259 ++++++++++++++++++ json-smart-action/mvnw.cmd | 149 ++++++++++ json-smart-action/pom.xml | 15 + .../.mvn/wrapper/maven-wrapper.properties | 19 ++ json-smart/mvnw | 259 ++++++++++++++++++ json-smart/mvnw.cmd | 149 ++++++++++ json-smart/pom.xml | 15 + 14 files changed, 1360 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/json-smart-formatting.yml create mode 100644 accessors-smart/.mvn/wrapper/maven-wrapper.properties create mode 100755 accessors-smart/mvnw create mode 100644 accessors-smart/mvnw.cmd create mode 100644 json-smart-action/.mvn/wrapper/maven-wrapper.properties create mode 100755 json-smart-action/mvnw create mode 100644 json-smart-action/mvnw.cmd create mode 100644 json-smart/.mvn/wrapper/maven-wrapper.properties create mode 100755 json-smart/mvnw create mode 100644 json-smart/mvnw.cmd diff --git a/.github/workflows/json-smart-formatting.yml b/.github/workflows/json-smart-formatting.yml new file mode 100644 index 0000000..facc672 --- /dev/null +++ b/.github/workflows/json-smart-formatting.yml @@ -0,0 +1,31 @@ + +name: json smart formatting +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + formatting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: 'temurin' + cache: 'maven' + + - name: Check formatting accessors-smart + run: cd accessors-smart; ./mvnw spotless:check + + - name: Check formatting json-smart + run: cd json-smart; ./mvnw spotless:check + + - name: Check formatting json-smart-action + run: cd json-smart-action; ./mvnw spotless:check diff --git a/.github/workflows/json-smart-unit-tests.yml b/.github/workflows/json-smart-unit-tests.yml index 89fbbaa..de3c842 100644 --- a/.github/workflows/json-smart-unit-tests.yml +++ b/.github/workflows/json-smart-unit-tests.yml @@ -26,10 +26,10 @@ jobs: cache: 'maven' - name: Unit tests accessors-smart - run: cd accessors-smart; mvn -B install; mvn -B clean test + run: cd accessors-smart; ./mvnw -B install; ./mvnw -B clean test - name: Unit tests json-smart - run: cd json-smart; mvn -B install; mvn -B clean test + run: cd json-smart; ./mvnw -B install; ./mvnw -B clean test - name: Unit tests json-smart-action - run: cd json-smart-action; mvn -B install; mvn -B clean test + run: cd json-smart-action; ./mvnw -B install; ./mvnw -B clean test diff --git a/accessors-smart/.mvn/wrapper/maven-wrapper.properties b/accessors-smart/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/accessors-smart/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/accessors-smart/mvnw b/accessors-smart/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/accessors-smart/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + 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" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/accessors-smart/mvnw.cmd b/accessors-smart/mvnw.cmd new file mode 100644 index 0000000..b150b91 --- /dev/null +++ b/accessors-smart/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/accessors-smart/pom.xml b/accessors-smart/pom.xml index 96fec44..b16ccdd 100644 --- a/accessors-smart/pom.xml +++ b/accessors-smart/pom.xml @@ -241,6 +241,21 @@ limitations under the License. + + com.diffplug.spotless + spotless-maven-plugin + 2.44.2 + + + + 1.25.2 + + true + false + + + + diff --git a/json-smart-action/.mvn/wrapper/maven-wrapper.properties b/json-smart-action/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/json-smart-action/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/json-smart-action/mvnw b/json-smart-action/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/json-smart-action/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + 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" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/json-smart-action/mvnw.cmd b/json-smart-action/mvnw.cmd new file mode 100644 index 0000000..b150b91 --- /dev/null +++ b/json-smart-action/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/json-smart-action/pom.xml b/json-smart-action/pom.xml index ddb8256..4abe7c0 100644 --- a/json-smart-action/pom.xml +++ b/json-smart-action/pom.xml @@ -231,6 +231,21 @@ + + com.diffplug.spotless + spotless-maven-plugin + 2.44.2 + + + + 1.25.2 + + true + false + + + + diff --git a/json-smart/.mvn/wrapper/maven-wrapper.properties b/json-smart/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..d58dfb7 --- /dev/null +++ b/json-smart/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/json-smart/mvnw b/json-smart/mvnw new file mode 100755 index 0000000..19529dd --- /dev/null +++ b/json-smart/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + 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" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/json-smart/mvnw.cmd b/json-smart/mvnw.cmd new file mode 100644 index 0000000..b150b91 --- /dev/null +++ b/json-smart/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/json-smart/pom.xml b/json-smart/pom.xml index f34b0ae..deb4d0b 100644 --- a/json-smart/pom.xml +++ b/json-smart/pom.xml @@ -252,6 +252,21 @@ limitations under the License. + + com.diffplug.spotless + spotless-maven-plugin + 2.44.2 + + + + 1.25.2 + + true + false + + + + From 6e5d25b3c9260fe8a657ba2f506a35ce850366da Mon Sep 17 00:00:00 2001 From: Christopher Cudennec Date: Sat, 15 Feb 2025 14:39:52 +0100 Subject: [PATCH 2/2] apply code formatting --- accessors-smart/pom.xml | 6 +- .../main/java/net/minidev/asm/ASMUtil.java | 490 +++--- .../main/java/net/minidev/asm/Accessor.java | 321 ++-- .../net/minidev/asm/BasicFiledFilter.java | 110 +- .../java/net/minidev/asm/BeansAccess.java | 419 +++-- .../net/minidev/asm/BeansAccessBuilder.java | 916 +++++----- .../net/minidev/asm/BeansAccessConfig.java | 144 +- .../java/net/minidev/asm/ConvertDate.java | 741 ++++---- .../net/minidev/asm/DefaultConverter.java | 538 +++--- .../net/minidev/asm/DynamicClassLoader.java | 118 +- .../java/net/minidev/asm/FieldFilter.java | 63 +- .../net/minidev/asm/ex/ConvertException.java | 42 +- .../minidev/asm/ex/NoSuchFieldException.java | 32 +- .../com/mindev/pojos/AccessorTestPojo.java | 49 +- .../test/java/net/minidev/asm/ASMTest.java | 242 ++- .../java/net/minidev/asm/AccessorTest.java | 141 +- .../net/minidev/asm/BTestBeansAccessB.java | 323 ++-- .../java/net/minidev/asm/TestDateConvert.java | 316 ++-- .../minidev/asm/TestDateConvertCustom.java | 22 +- .../java/net/minidev/asm/TestNewInstance.java | 13 +- .../java/net/minidev/asm/bean/BBoolPriv.java | 14 +- .../java/net/minidev/asm/bean/BBoolPub.java | 2 +- .../net/minidev/asm/bean/BBooleanPriv.java | 14 +- .../net/minidev/asm/bean/BBooleanPub.java | 2 +- .../java/net/minidev/asm/bean/BEnumPriv.java | 14 +- .../net/minidev/asm/bean/BEnumPrivAc.java | 84 +- .../java/net/minidev/asm/bean/BEnumPub.java | 2 +- .../java/net/minidev/asm/bean/BLongPriv.java | 14 +- .../net/minidev/asm/bean/BLongPrivAc.java | 73 +- .../java/net/minidev/asm/bean/BLongPub.java | 2 +- .../java/net/minidev/asm/bean/BLongPubAc.java | 73 +- .../net/minidev/asm/bean/BObjectPriv.java | 14 +- .../java/net/minidev/asm/bean/BObjectPub.java | 2 +- .../java/net/minidev/asm/bean/BStrPriv.java | 15 +- .../java/net/minidev/asm/bean/BStrPrivAc.java | 79 +- .../java/net/minidev/asm/bean/BStrPub.java | 2 +- .../java/net/minidev/asm/bean/BStrPubAc.java | 79 +- .../test/java/net/minidev/asm/bean/BTest.java | 58 +- .../test/java/net/minidev/asm/bean/TEnum.java | 4 +- .../net/minidev/asm/bean/TestAsmAtom.java | 193 +-- json-smart-action/pom.xml | 6 +- .../minidev/json/actions/ElementRemover.java | 56 +- .../net/minidev/json/actions/PathLocator.java | 93 +- .../net/minidev/json/actions/PathRemover.java | 93 +- .../minidev/json/actions/PathReplicator.java | 97 +- .../minidev/json/actions/PathsRetainer.java | 128 +- .../actions/navigate/CopyPathsAction.java | 243 ++- .../actions/navigate/JSONNavigateAction.java | 11 +- .../json/actions/navigate/JSONNavigator.java | 15 +- .../json/actions/navigate/NavigateAction.java | 250 +-- .../json/actions/navigate/TreeNavigator.java | 225 ++- .../json/actions/navigate/package-info.java | 38 +- .../json/actions/path/DotDelimiter.java | 18 +- .../json/actions/path/PathDelimiter.java | 58 +- .../json/actions/path/SlashDelimiter.java | 20 +- .../minidev/json/actions/path/TreePath.java | 442 ++--- .../actions/traverse/JSONTraverseAction.java | 7 +- .../json/actions/traverse/JSONTraverser.java | 31 +- .../actions/traverse/KeysPrintAction.java | 90 +- .../traverse/LocatePathsJsonAction.java | 159 +- .../traverse/RemoveElementsJsonAction.java | 111 +- .../traverse/RemovePathsJsonAction.java | 102 +- .../traverse/RetainPathsJsonAction.java | 201 +-- .../actions/traverse/TreeTraverseAction.java | 135 +- .../json/actions/traverse/TreeTraverser.java | 137 +- .../json/actions/traverse/package-info.java | 38 +- .../json/test/actions/ElementRemoverTest.java | 100 +- .../test/actions/KeysPrintActionTest.java | 62 +- .../json/test/actions/PathLocatorTest.java | 244 +-- .../json/test/actions/PathRemoverTest.java | 210 ++- .../json/test/actions/PathReplicatorTest.java | 398 +++-- .../json/test/actions/PathsRetainerTest.java | 277 +-- .../json/test/actions/TreePathTest.java | 166 +- json-smart/pom.xml | 6 +- .../main/java/net/minidev/json/JSONArray.java | 213 ++- .../main/java/net/minidev/json/JSONAware.java | 13 +- .../java/net/minidev/json/JSONAwareEx.java | 15 +- .../main/java/net/minidev/json/JSONNavi.java | 1379 +++++++-------- .../java/net/minidev/json/JSONObject.java | 442 +++-- .../net/minidev/json/JSONStreamAware.java | 11 +- .../net/minidev/json/JSONStreamAwareEx.java | 11 +- .../main/java/net/minidev/json/JSONStyle.java | 337 ++-- .../main/java/net/minidev/json/JSONUtil.java | 392 ++--- .../main/java/net/minidev/json/JSONValue.java | 1225 +++++++------ .../java/net/minidev/json/JStylerObj.java | 543 +++--- .../net/minidev/json/annotate/JsonIgnore.java | 26 +- .../json/annotate/JsonSmartAnnotation.java | 10 +- .../net/minidev/json/parser/JSONParser.java | 548 +++--- .../minidev/json/parser/JSONParserBase.java | 1543 ++++++++--------- .../json/parser/JSONParserByteArray.java | 140 +- .../json/parser/JSONParserInputStream.java | 65 +- .../minidev/json/parser/JSONParserMemory.java | 196 +-- .../minidev/json/parser/JSONParserReader.java | 106 +- .../minidev/json/parser/JSONParserStream.java | 209 ++- .../minidev/json/parser/JSONParserString.java | 134 +- .../minidev/json/parser/ParseException.java | 197 ++- .../net/minidev/json/reader/ArrayWriter.java | 24 +- .../net/minidev/json/reader/BeansWriter.java | 95 +- .../minidev/json/reader/BeansWriterASM.java | 47 +- .../json/reader/BeansWriterASMRemap.java | 69 +- .../net/minidev/json/reader/JsonWriter.java | 776 +++++---- .../net/minidev/json/reader/JsonWriterI.java | 4 +- .../net/minidev/json/writer/ArraysMapper.java | 505 +++--- .../net/minidev/json/writer/BeansMapper.java | 243 ++- .../minidev/json/writer/CollectionMapper.java | 431 +++-- .../minidev/json/writer/CompessorMapper.java | 382 ++-- .../minidev/json/writer/DefaultMapper.java | 71 +- .../json/writer/DefaultMapperCollection.java | 88 +- .../json/writer/DefaultMapperOrdered.java | 68 +- .../net/minidev/json/writer/FakeMapper.java | 65 +- .../net/minidev/json/writer/JsonReader.java | 236 ++- .../net/minidev/json/writer/JsonReaderI.java | 136 +- .../minidev/json/writer/MapperRemapped.java | 92 +- .../minidev/json/writer/UpdaterMapper.java | 137 +- .../net/minidev/json/test/JSONObjectTest.java | 352 ++-- .../net/minidev/json/test/JSONSimpleTest.java | 33 +- .../net/minidev/json/test/MustThrows.java | 65 +- .../json/test/SerializeReadonlyField.java | 80 +- .../json/test/TestBigDigitUnrestricted.java | 46 +- .../net/minidev/json/test/TestBigValue.java | 60 +- .../minidev/json/test/TestCVE202457699.java | 94 +- .../net/minidev/json/test/TestCompressor.java | 98 +- .../json/test/TestCompressorFlags.java | 163 +- .../java/net/minidev/json/test/TestFloat.java | 128 +- .../minidev/json/test/TestFloatStrict.java | 37 +- .../minidev/json/test/TestGitHubIssue.java | 23 +- .../java/net/minidev/json/test/TestInts.java | 171 +- .../minidev/json/test/TestInvalidNumber.java | 120 +- .../net/minidev/json/test/TestKeyword.java | 67 +- .../java/net/minidev/json/test/TestMisc.java | 108 +- .../java/net/minidev/json/test/TestNavi.java | 140 +- .../json/test/TestNumberPrecision.java | 72 +- .../net/minidev/json/test/TestOverflow.java | 119 +- .../net/minidev/json/test/TestStrict.java | 98 +- .../net/minidev/json/test/TestString.java | 90 +- .../minidev/json/test/TestStringStrict.java | 29 +- .../net/minidev/json/test/TestTruncated.java | 31 +- .../java/net/minidev/json/test/TestUtf8.java | 107 +- .../json/test/strict/TestExcessiveComma.java | 97 +- .../json/test/strict/TestSpecialChar.java | 36 +- .../json/test/strict/TestTaillingJunk.java | 83 +- .../json/test/strict/TestZeroLead.java | 91 +- .../json/test/writer/TestWriteFeatures.java | 41 +- .../json/testMapping/TestAdvancedMapper.java | 53 +- .../testMapping/TestCustomMappingInstant.java | 111 +- .../minidev/json/testMapping/TestDate.java | 32 +- .../json/testMapping/TestFieldRename.java | 38 +- .../json/testMapping/TestMapBeans.java | 214 ++- .../json/testMapping/TestMapPrimArrays.java | 89 +- .../json/testMapping/TestMapPublic.java | 136 +- .../json/testMapping/TestMapPublic2.java | 51 +- .../json/testMapping/TestSerPrimArrays.java | 66 +- .../minidev/json/testMapping/TestUUID.java | 103 +- .../minidev/json/testMapping/TestUpdater.java | 104 +- 154 files changed, 12288 insertions(+), 12665 deletions(-) diff --git a/accessors-smart/pom.xml b/accessors-smart/pom.xml index b16ccdd..b3c9306 100644 --- a/accessors-smart/pom.xml +++ b/accessors-smart/pom.xml @@ -247,11 +247,15 @@ limitations under the License. 2.44.2 + + src/main/java/**/*.java + src/test/java/**/*.java + 1.25.2 true - false + true diff --git a/accessors-smart/src/main/java/net/minidev/asm/ASMUtil.java b/accessors-smart/src/main/java/net/minidev/asm/ASMUtil.java index 23ec793..7c1cd35 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/ASMUtil.java +++ b/accessors-smart/src/main/java/net/minidev/asm/ASMUtil.java @@ -21,270 +21,266 @@ import java.lang.reflect.Field; import java.util.HashMap; - import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Type; /** * ASM Utils used to simplify class generation - * + * * @author uriel Chemouni */ public class ASMUtil { - /** - * default constructor - */ - public ASMUtil() { - super(); - } - /** - * Append the call of proper autoboxing method for the given primitive type. - * - * @param mv MethodVisitor - * @param clz expected class - */ - public static void autoBoxing(MethodVisitor mv, Class clz) { - autoBoxing(mv, Type.getType(clz)); - } + /** default constructor */ + public ASMUtil() { + super(); + } - /** - * Extract all Accessor for the field of the given class. - * - * @param type type - * @param filter FieldFilter - * @return all Accessor available - */ - static public Accessor[] getAccessors(Class type, FieldFilter filter) { - Class nextClass = type; - HashMap map = new HashMap(); - if (filter == null) - filter = BasicFiledFilter.SINGLETON; - while (nextClass != Object.class) { - Field[] declaredFields = nextClass.getDeclaredFields(); + /** + * Append the call of proper autoboxing method for the given primitive type. + * + * @param mv MethodVisitor + * @param clz expected class + */ + public static void autoBoxing(MethodVisitor mv, Class clz) { + autoBoxing(mv, Type.getType(clz)); + } - for (Field field : declaredFields) { - String fn = field.getName(); - if (map.containsKey(fn)) - continue; - Accessor acc = new Accessor(nextClass, field, filter); - if (!acc.isUsable()) - continue; - map.put(fn, acc); - } - nextClass = nextClass.getSuperclass(); - } - return map.values().toArray(new Accessor[map.size()]); - } + /** + * Extract all Accessor for the field of the given class. + * + * @param type type + * @param filter FieldFilter + * @return all Accessor available + */ + public static Accessor[] getAccessors(Class type, FieldFilter filter) { + Class nextClass = type; + HashMap map = new HashMap(); + if (filter == null) filter = BasicFiledFilter.SINGLETON; + while (nextClass != Object.class) { + Field[] declaredFields = nextClass.getDeclaredFields(); - /** - * Append the call of proper autoboxing method for the given primitive type. - * - * @param mv MethodVisitor - * @param fieldType expected class - */ - protected static void autoBoxing(MethodVisitor mv, Type fieldType) { - switch (fieldType.getSort()) { - case Type.BOOLEAN: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - break; - case Type.BYTE: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); - break; - case Type.CHAR: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); - break; - case Type.SHORT: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); - break; - case Type.INT: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); - break; - case Type.FLOAT: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); - break; - case Type.LONG: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); - break; - case Type.DOUBLE: - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); - break; - } - } + for (Field field : declaredFields) { + String fn = field.getName(); + if (map.containsKey(fn)) continue; + Accessor acc = new Accessor(nextClass, field, filter); + if (!acc.isUsable()) continue; + map.put(fn, acc); + } + nextClass = nextClass.getSuperclass(); + } + return map.values().toArray(new Accessor[map.size()]); + } - /** - * Append the call of proper extract primitive type of an boxed object. - * - * @param mv MethodVisitor - * @param fieldType expected class - */ - protected static void autoUnBoxing1(MethodVisitor mv, Type fieldType) { - switch (fieldType.getSort()) { - case Type.BOOLEAN: - mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); - break; - case Type.BYTE: - mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); - break; - case Type.CHAR: - mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); - break; - case Type.SHORT: - mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); - break; - case Type.INT: - mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); - break; - case Type.FLOAT: - mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); - break; - case Type.LONG: - mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); - break; - case Type.DOUBLE: - mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); - break; - case Type.ARRAY: - mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); - break; - default: - mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); - } - } + /** + * Append the call of proper autoboxing method for the given primitive type. + * + * @param mv MethodVisitor + * @param fieldType expected class + */ + protected static void autoBoxing(MethodVisitor mv, Type fieldType) { + switch (fieldType.getSort()) { + case Type.BOOLEAN: + mv.visitMethodInsn( + INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + break; + case Type.BYTE: + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); + break; + case Type.CHAR: + mv.visitMethodInsn( + INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); + break; + case Type.SHORT: + mv.visitMethodInsn( + INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); + break; + case Type.INT: + mv.visitMethodInsn( + INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + break; + case Type.FLOAT: + mv.visitMethodInsn( + INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); + break; + case Type.LONG: + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); + break; + case Type.DOUBLE: + mv.visitMethodInsn( + INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + break; + } + } - /** - * Append the call of proper extract primitive type of an boxed object. this - * method use Number interface to unbox object - * - * @param mv MethodVisitor - * @param fieldType expected class - */ - protected static void autoUnBoxing2(MethodVisitor mv, Type fieldType) { - switch (fieldType.getSort()) { - case Type.BOOLEAN: - mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); - break; - case Type.BYTE: - mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "byteValue", "()B", false); - break; - case Type.CHAR: - mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); - break; - case Type.SHORT: - mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "shortValue", "()S", false); - break; - case Type.INT: - mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "intValue", "()I", false); - break; - case Type.FLOAT: - mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "floatValue", "()F", false); - break; - case Type.LONG: - mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "longValue", "()J", false); - break; - case Type.DOUBLE: - mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "doubleValue", "()D", false); - break; - case Type.ARRAY: - mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); - break; - default: - mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); - } - } + /** + * Append the call of proper extract primitive type of an boxed object. + * + * @param mv MethodVisitor + * @param fieldType expected class + */ + protected static void autoUnBoxing1(MethodVisitor mv, Type fieldType) { + switch (fieldType.getSort()) { + case Type.BOOLEAN: + mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); + break; + case Type.BYTE: + mv.visitTypeInsn(CHECKCAST, "java/lang/Byte"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false); + break; + case Type.CHAR: + mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); + break; + case Type.SHORT: + mv.visitTypeInsn(CHECKCAST, "java/lang/Short"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false); + break; + case Type.INT: + mv.visitTypeInsn(CHECKCAST, "java/lang/Integer"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); + break; + case Type.FLOAT: + mv.visitTypeInsn(CHECKCAST, "java/lang/Float"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false); + break; + case Type.LONG: + mv.visitTypeInsn(CHECKCAST, "java/lang/Long"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false); + break; + case Type.DOUBLE: + mv.visitTypeInsn(CHECKCAST, "java/lang/Double"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false); + break; + case Type.ARRAY: + mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); + break; + default: + mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); + } + } - /** - * return a array of new Label (used for switch/case generation) - * - * @param cnt number of label to return - * @return a Label array - */ - public static Label[] newLabels(int cnt) { - Label[] r = new Label[cnt]; - for (int i = 0; i < cnt; i++) - r[i] = new Label(); - return r; - } + /** + * Append the call of proper extract primitive type of an boxed object. this method use Number + * interface to unbox object + * + * @param mv MethodVisitor + * @param fieldType expected class + */ + protected static void autoUnBoxing2(MethodVisitor mv, Type fieldType) { + switch (fieldType.getSort()) { + case Type.BOOLEAN: + mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); + break; + case Type.BYTE: + mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "byteValue", "()B", false); + break; + case Type.CHAR: + mv.visitTypeInsn(CHECKCAST, "java/lang/Character"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false); + break; + case Type.SHORT: + mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "shortValue", "()S", false); + break; + case Type.INT: + mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "intValue", "()I", false); + break; + case Type.FLOAT: + mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "floatValue", "()F", false); + break; + case Type.LONG: + mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "longValue", "()J", false); + break; + case Type.DOUBLE: + mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "doubleValue", "()D", false); + break; + case Type.ARRAY: + mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); + break; + default: + mv.visitTypeInsn(CHECKCAST, fieldType.getInternalName()); + } + } - /** - * Generates a setter method name for a given field name. - * - * @param key the field name - * @return setter name - */ - public static String getSetterName(String key) { - int len = key.length(); - char[] b = new char[len + 3]; - b[0] = 's'; - b[1] = 'e'; - b[2] = 't'; - char c = key.charAt(0); - if (c >= 'a' && c <= 'z') - c += 'A' - 'a'; - b[3] = c; - for (int i = 1; i < len; i++) { - b[i + 3] = key.charAt(i); - } - return new String(b); - } + /** + * return a array of new Label (used for switch/case generation) + * + * @param cnt number of label to return + * @return a Label array + */ + public static Label[] newLabels(int cnt) { + Label[] r = new Label[cnt]; + for (int i = 0; i < cnt; i++) r[i] = new Label(); + return r; + } - /** - * Generates a getter method name for a given field name. - * - * @param key the field name - * @return getter name - */ - public static String getGetterName(String key) { - int len = key.length(); - char[] b = new char[len + 3]; - b[0] = 'g'; - b[1] = 'e'; - b[2] = 't'; - char c = key.charAt(0); - if (c >= 'a' && c <= 'z') - c += 'A' - 'a'; - b[3] = c; - for (int i = 1; i < len; i++) { - b[i + 3] = key.charAt(i); - } - return new String(b); - } + /** + * Generates a setter method name for a given field name. + * + * @param key the field name + * @return setter name + */ + public static String getSetterName(String key) { + int len = key.length(); + char[] b = new char[len + 3]; + b[0] = 's'; + b[1] = 'e'; + b[2] = 't'; + char c = key.charAt(0); + if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + b[3] = c; + for (int i = 1; i < len; i++) { + b[i + 3] = key.charAt(i); + } + return new String(b); + } - /** - * Generates a boolean getter method name (is-method) for a given field name. - * - * @param key the boolean field name - * @return boolean getter name - */ - public static String getIsName(String key) { - int len = key.length(); - char[] b = new char[len + 2]; - b[0] = 'i'; - b[1] = 's'; - char c = key.charAt(0); - if (c >= 'a' && c <= 'z') - c += 'A' - 'a'; - b[2] = c; - for (int i = 1; i < len; i++) { - b[i + 2] = key.charAt(i); - } - return new String(b); - } + /** + * Generates a getter method name for a given field name. + * + * @param key the field name + * @return getter name + */ + public static String getGetterName(String key) { + int len = key.length(); + char[] b = new char[len + 3]; + b[0] = 'g'; + b[1] = 'e'; + b[2] = 't'; + char c = key.charAt(0); + if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + b[3] = c; + for (int i = 1; i < len; i++) { + b[i + 3] = key.charAt(i); + } + return new String(b); + } + /** + * Generates a boolean getter method name (is-method) for a given field name. + * + * @param key the boolean field name + * @return boolean getter name + */ + public static String getIsName(String key) { + int len = key.length(); + char[] b = new char[len + 2]; + b[0] = 'i'; + b[1] = 's'; + char c = key.charAt(0); + if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + b[2] = c; + for (int i = 1; i < len; i++) { + b[i + 2] = key.charAt(i); + } + return new String(b); + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/Accessor.java b/accessors-smart/src/main/java/net/minidev/asm/Accessor.java index 0c1b59a..c050410 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/Accessor.java +++ b/accessors-smart/src/main/java/net/minidev/asm/Accessor.java @@ -22,173 +22,164 @@ /** * Contains all information needed to access a java field. - * - * field, getter setter - * - * this object is used internally by BeansAccess - * + * + *

field, getter setter + * + *

this object is used internally by BeansAccess + * * @see BeansAccess - * * @author Uriel Chemouni */ public class Accessor { - /** - * Field to access - */ - protected Field field; - /** - * Setter Methods if available - */ - protected Method setter; - /** - * getter Methods if available - */ - protected Method getter; - /** - * Filed index in object - */ - protected int index; - /** - * Filed Class - */ - protected Class type; - /** - * Filed Type using JDK 5+ generics if available - */ - protected Type genericType; - /** - * The name of the field. - */ - protected String fieldName; - - /** - * getter for index - * @return Index - */ - public int getIndex() { - return index; - } - - /** - * is the field access using Field access type - * @return if Accessor is public - */ - public boolean isPublic() { - return setter == null && getter == null; - } - - /** - * is the field is an enum field - * @return if Accessor return an Enum Class - */ - public boolean isEnum() { - return type.isEnum(); - } - - /** - * return the field name - * @return the field name - */ - public String getName() { - return fieldName; - } - - /** - * return field Class - * @return field Class - */ - public Class getType() { - return type; - } - - /** - * return generics field Type. - * @return generics field Type. - */ - public Type getGenericType() { - return genericType; - } - - /** - * Determines if the field is accessible for reading or writing operations. - * - * @return true if the field can be read or write - */ - public boolean isUsable() { - return field != null || getter != null || setter != null; - } - - /** - * Checks if the field is readable, either directly or through a getter method. - * - * @return true if the field can be read - */ - public boolean isReadable() { - return field != null || getter != null; - } - - /** - * Determines if the field is writable, either directly or through a setter method. - * - * @return true if the field can be write - */ - public boolean isWritable() { - return field != null || setter != null; - } - - /** - * build accessor for a field - * - * @param c the handled class - * @param field the field to access - * @param filter field filter - */ - public Accessor(Class c, Field field, FieldFilter filter) { - this.fieldName = field.getName(); - int m = field.getModifiers(); - - if ((m & (Modifier.STATIC | Modifier.TRANSIENT)) > 0) - return; - - if ((m & Modifier.PUBLIC) > 0) - this.field = field; - - String name = ASMUtil.getSetterName(field.getName()); - try { - setter = c.getDeclaredMethod(name, field.getType()); - } catch (Exception e) { - } - boolean isBool = field.getType().equals(Boolean.TYPE); - if (isBool) { - name = ASMUtil.getIsName(field.getName()); - } else { - name = ASMUtil.getGetterName(field.getName()); - } - try { - getter = c.getDeclaredMethod(name); - } catch (Exception e) { - } - if (getter == null && isBool) { - try { - getter = c.getDeclaredMethod(ASMUtil.getGetterName(field.getName())); - } catch (Exception e) { - } - } - - if (this.field == null && getter == null && setter == null) - return; - - if (getter != null && !filter.canUse(field, getter)) - getter = null; - - if (setter != null && !filter.canUse(field, setter)) - setter = null; - - // no access disable - if (getter == null && setter == null && this.field == null) - return; - - this.type = field.getType(); - this.genericType = field.getGenericType(); - } + /** Field to access */ + protected Field field; + + /** Setter Methods if available */ + protected Method setter; + + /** getter Methods if available */ + protected Method getter; + + /** Filed index in object */ + protected int index; + + /** Filed Class */ + protected Class type; + + /** Filed Type using JDK 5+ generics if available */ + protected Type genericType; + + /** The name of the field. */ + protected String fieldName; + + /** + * getter for index + * + * @return Index + */ + public int getIndex() { + return index; + } + + /** + * is the field access using Field access type + * + * @return if Accessor is public + */ + public boolean isPublic() { + return setter == null && getter == null; + } + + /** + * is the field is an enum field + * + * @return if Accessor return an Enum Class + */ + public boolean isEnum() { + return type.isEnum(); + } + + /** + * return the field name + * + * @return the field name + */ + public String getName() { + return fieldName; + } + + /** + * return field Class + * + * @return field Class + */ + public Class getType() { + return type; + } + + /** + * return generics field Type. + * + * @return generics field Type. + */ + public Type getGenericType() { + return genericType; + } + + /** + * Determines if the field is accessible for reading or writing operations. + * + * @return true if the field can be read or write + */ + public boolean isUsable() { + return field != null || getter != null || setter != null; + } + + /** + * Checks if the field is readable, either directly or through a getter method. + * + * @return true if the field can be read + */ + public boolean isReadable() { + return field != null || getter != null; + } + + /** + * Determines if the field is writable, either directly or through a setter method. + * + * @return true if the field can be write + */ + public boolean isWritable() { + return field != null || setter != null; + } + + /** + * build accessor for a field + * + * @param c the handled class + * @param field the field to access + * @param filter field filter + */ + public Accessor(Class c, Field field, FieldFilter filter) { + this.fieldName = field.getName(); + int m = field.getModifiers(); + + if ((m & (Modifier.STATIC | Modifier.TRANSIENT)) > 0) return; + + if ((m & Modifier.PUBLIC) > 0) this.field = field; + + String name = ASMUtil.getSetterName(field.getName()); + try { + setter = c.getDeclaredMethod(name, field.getType()); + } catch (Exception e) { + } + boolean isBool = field.getType().equals(Boolean.TYPE); + if (isBool) { + name = ASMUtil.getIsName(field.getName()); + } else { + name = ASMUtil.getGetterName(field.getName()); + } + try { + getter = c.getDeclaredMethod(name); + } catch (Exception e) { + } + if (getter == null && isBool) { + try { + getter = c.getDeclaredMethod(ASMUtil.getGetterName(field.getName())); + } catch (Exception e) { + } + } + + if (this.field == null && getter == null && setter == null) return; + + if (getter != null && !filter.canUse(field, getter)) getter = null; + + if (setter != null && !filter.canUse(field, setter)) setter = null; + + // no access disable + if (getter == null && setter == null && this.field == null) return; + + this.type = field.getType(); + this.genericType = field.getGenericType(); + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/BasicFiledFilter.java b/accessors-smart/src/main/java/net/minidev/asm/BasicFiledFilter.java index 2f5f7c5..e6b0640 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/BasicFiledFilter.java +++ b/accessors-smart/src/main/java/net/minidev/asm/BasicFiledFilter.java @@ -4,67 +4,65 @@ import java.lang.reflect.Method; /** - * A basic implementation of the {@link FieldFilter} interface that permits all operations on fields. - * This implementation returns {@code true} for all checks, indicating that any field can be used, read, and written. - * It serves as a default or fallback strategy when no specific field filtering logic is required. + * A basic implementation of the {@link FieldFilter} interface that permits all operations on + * fields. This implementation returns {@code true} for all checks, indicating that any field can be + * used, read, and written. It serves as a default or fallback strategy when no specific field + * filtering logic is required. */ public class BasicFiledFilter implements FieldFilter { - /** - * default constructor - */ - public BasicFiledFilter() { - super(); - } + /** default constructor */ + public BasicFiledFilter() { + super(); + } - /** - * A singleton instance of {@code BasicFieldFilter}. - * Since the filter does not maintain any state and allows all operations, it can be reused across the application. - */ - public final static BasicFiledFilter SINGLETON = new BasicFiledFilter(); + /** + * A singleton instance of {@code BasicFieldFilter}. Since the filter does not maintain any state + * and allows all operations, it can be reused across the application. + */ + public static final BasicFiledFilter SINGLETON = new BasicFiledFilter(); - /** - * Always allows using the specified field. - * - * @param field The field to check. - * @return Always returns {@code true}. - */ - @Override - public boolean canUse(Field field) { - return true; - } + /** + * Always allows using the specified field. + * + * @param field The field to check. + * @return Always returns {@code true}. + */ + @Override + public boolean canUse(Field field) { + return true; + } - /** - * Always allows using the specified field in conjunction with a method. - * - * @param field The field to check. - * @param method The method to check. This parameter is not used in the current implementation. - * @return Always returns {@code true}. - */ - @Override - public boolean canUse(Field field, Method method) { - return true; - } + /** + * Always allows using the specified field in conjunction with a method. + * + * @param field The field to check. + * @param method The method to check. This parameter is not used in the current implementation. + * @return Always returns {@code true}. + */ + @Override + public boolean canUse(Field field, Method method) { + return true; + } - /** - * Always allows reading the specified field. - * - * @param field The field to check. - * @return Always returns {@code true}. - */ - @Override - public boolean canRead(Field field) { - return true; - } - - /** - * Always allows writing to the specified field. - * - * @param field The field to check. - * @return Always returns {@code true}. - */ - @Override - public boolean canWrite(Field field) { - return true; - } + /** + * Always allows reading the specified field. + * + * @param field The field to check. + * @return Always returns {@code true}. + */ + @Override + public boolean canRead(Field field) { + return true; + } + /** + * Always allows writing to the specified field. + * + * @param field The field to check. + * @return Always returns {@code true}. + */ + @Override + public boolean canWrite(Field field) { + return true; + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/BeansAccess.java b/accessors-smart/src/main/java/net/minidev/asm/BeansAccess.java index 4789da5..21ef4ef 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/BeansAccess.java +++ b/accessors-smart/src/main/java/net/minidev/asm/BeansAccess.java @@ -21,218 +21,217 @@ import java.util.concurrent.ConcurrentHashMap; /** - * Allow access reflect field using runtime generated accessor. BeansAccessor is - * faster than java.lang.reflect.Method.invoke() - * + * Allow access reflect field using runtime generated accessor. BeansAccessor is faster than + * java.lang.reflect.Method.invoke() + * * @param the type of the bean being accessed * @author uriel Chemouni */ public abstract class BeansAccess { - /** - * default constuctor - */ - public BeansAccess() { - super(); - } - - private HashMap map; - private Accessor[] accs; - - /** - * set Accessor - * @param accs Accessor list - */ - protected void setAccessor(Accessor[] accs) { - int i = 0; - this.accs = accs; - map = new HashMap(); - for (Accessor acc : accs) { - acc.index = i++; - map.put(acc.getName(), acc); - } - } - - /** - * get internal map - * @return a map - */ - public HashMap getMap() { - return map; - } - - /** - * get internal accessor - * @return Accessor list - */ - public Accessor[] getAccessors() { - return accs; - } - - /** - * cache used to store built BeansAccess - */ - private static ConcurrentHashMap, BeansAccess> cache = new ConcurrentHashMap, BeansAccess>(); - - // private final static ConcurrentHashMap> cache; - - /** - * return the BeansAccess corresponding to a type - * - * @param type to be access - * @param

working type - * @return the BeansAccess - */ - static public

BeansAccess

get(Class

type) { - return get(type, null); - } - - /** - * return the BeansAccess corresponding to a type - * - * @param filter FieldFilter - * @param type to be access - * @param

working type - * @return the BeansAccess - */ - static public

BeansAccess

get(Class

type, FieldFilter filter) { - { - @SuppressWarnings("unchecked") - BeansAccess

access = (BeansAccess

) cache.get(type); - if (access != null) - return access; - } - // extract all access methods - Accessor[] accs = ASMUtil.getAccessors(type, filter); - - // create new class name - String className = type.getName(); - String accessClassName; - if (className.startsWith("java.util.")) - accessClassName = "net.minidev.asm." + className + "AccAccess"; - else - accessClassName = className.concat("AccAccess"); - - // extend class base loader - DynamicClassLoader loader = new DynamicClassLoader(type.getClassLoader()); - // try to load existing class - Class accessClass = null; - try { - accessClass = loader.loadClass(accessClassName); - } catch (ClassNotFoundException ignored) { - } - - LinkedList> parentClasses = getParents(type); - - // if the class do not exists build it - if (accessClass == null) { - BeansAccessBuilder builder = new BeansAccessBuilder(type, accs, loader); - for (Class c : parentClasses) - builder.addConversion(BeansAccessConfig.classMapper.get(c)); - accessClass = builder.bulid(); - } - try { - @SuppressWarnings("unchecked") - BeansAccess

access = (BeansAccess

) accessClass.newInstance(); - access.setAccessor(accs); - cache.putIfAbsent(type, access); - // add fieldname alias - for (Class c : parentClasses) - addAlias(access, BeansAccessConfig.classFiledNameMapper.get(c)); - return access; - } catch (Exception ex) { - throw new RuntimeException("Error constructing accessor class: " + accessClassName, ex); - } - } - - /** - * @param type current type - * @return parents hierarchy - */ - private static LinkedList> getParents(Class type) { - LinkedList> m = new LinkedList>(); - while (type != null && !type.equals(Object.class)) { - m.addLast(type); - for (Class c : type.getInterfaces()) - m.addLast(c); - type = type.getSuperclass(); - } - m.addLast(Object.class); - return m; - } - - /** - * @param access accessor to use - * @param m mapping - */ - private static void addAlias(BeansAccess access, HashMap m) { - // HashMap m = - // BeansAccessConfig.classFiledNameMapper.get(type); - if (m == null) - return; - HashMap changes = new HashMap(); - for (Entry e : m.entrySet()) { - Accessor a1 = access.map.get(e.getValue()); - if (a1 != null) - changes.put(e.getValue(), a1); - } - access.map.putAll(changes); - } - - /** - * set field value by field index - * - * @param object object to alter - * @param methodIndex field id to update - * @param value new value - */ - abstract public void set(T object, int methodIndex, Object value); - - /** - * get field value by field index - * @param object object to operate - * @param methodIndex field number to operate - * @return value of the field - */ - abstract public Object get(T object, int methodIndex); - - /** - * create a new targeted object - * @return new instance - */ - abstract public T newInstance(); - - /** - * set field value by field name - * @param object target object - * @param methodName methodName - * @param value new field value - */ - public void set(T object, String methodName, Object value) { - int i = getIndex(methodName); - if (i == -1) - throw new net.minidev.asm.ex.NoSuchFieldException(methodName + " in " + object.getClass() + " to put value : " + value); - set(object, i, value); - } - - /** - * get field value by field name - * @param object object to operate - * @param methodName getter to call - * @return field value returned by the getter - */ - public Object get(T object, String methodName) { - return get(object, getIndex(methodName)); - } - - /** - * Returns the index of the field accessor. - * @param name field name - * @return id of the field - */ - public int getIndex(String name) { - Accessor ac = map.get(name); - if (ac == null) - return -1; - return ac.index; - } + /** default constuctor */ + public BeansAccess() { + super(); + } + + private HashMap map; + private Accessor[] accs; + + /** + * set Accessor + * + * @param accs Accessor list + */ + protected void setAccessor(Accessor[] accs) { + int i = 0; + this.accs = accs; + map = new HashMap(); + for (Accessor acc : accs) { + acc.index = i++; + map.put(acc.getName(), acc); + } + } + + /** + * get internal map + * + * @return a map + */ + public HashMap getMap() { + return map; + } + + /** + * get internal accessor + * + * @return Accessor list + */ + public Accessor[] getAccessors() { + return accs; + } + + /** cache used to store built BeansAccess */ + private static ConcurrentHashMap, BeansAccess> cache = + new ConcurrentHashMap, BeansAccess>(); + + // private final static ConcurrentHashMap> cache; + + /** + * return the BeansAccess corresponding to a type + * + * @param type to be access + * @param

working type + * @return the BeansAccess + */ + public static

BeansAccess

get(Class

type) { + return get(type, null); + } + + /** + * return the BeansAccess corresponding to a type + * + * @param filter FieldFilter + * @param type to be access + * @param

working type + * @return the BeansAccess + */ + public static

BeansAccess

get(Class

type, FieldFilter filter) { + { + @SuppressWarnings("unchecked") + BeansAccess

access = (BeansAccess

) cache.get(type); + if (access != null) return access; + } + // extract all access methods + Accessor[] accs = ASMUtil.getAccessors(type, filter); + + // create new class name + String className = type.getName(); + String accessClassName; + if (className.startsWith("java.util.")) + accessClassName = "net.minidev.asm." + className + "AccAccess"; + else accessClassName = className.concat("AccAccess"); + + // extend class base loader + DynamicClassLoader loader = new DynamicClassLoader(type.getClassLoader()); + // try to load existing class + Class accessClass = null; + try { + accessClass = loader.loadClass(accessClassName); + } catch (ClassNotFoundException ignored) { + } + + LinkedList> parentClasses = getParents(type); + + // if the class do not exists build it + if (accessClass == null) { + BeansAccessBuilder builder = new BeansAccessBuilder(type, accs, loader); + for (Class c : parentClasses) builder.addConversion(BeansAccessConfig.classMapper.get(c)); + accessClass = builder.bulid(); + } + try { + @SuppressWarnings("unchecked") + BeansAccess

access = (BeansAccess

) accessClass.newInstance(); + access.setAccessor(accs); + cache.putIfAbsent(type, access); + // add fieldname alias + for (Class c : parentClasses) + addAlias(access, BeansAccessConfig.classFiledNameMapper.get(c)); + return access; + } catch (Exception ex) { + throw new RuntimeException("Error constructing accessor class: " + accessClassName, ex); + } + } + + /** + * @param type current type + * @return parents hierarchy + */ + private static LinkedList> getParents(Class type) { + LinkedList> m = new LinkedList>(); + while (type != null && !type.equals(Object.class)) { + m.addLast(type); + for (Class c : type.getInterfaces()) m.addLast(c); + type = type.getSuperclass(); + } + m.addLast(Object.class); + return m; + } + + /** + * @param access accessor to use + * @param m mapping + */ + private static void addAlias(BeansAccess access, HashMap m) { + // HashMap m = + // BeansAccessConfig.classFiledNameMapper.get(type); + if (m == null) return; + HashMap changes = new HashMap(); + for (Entry e : m.entrySet()) { + Accessor a1 = access.map.get(e.getValue()); + if (a1 != null) changes.put(e.getValue(), a1); + } + access.map.putAll(changes); + } + + /** + * set field value by field index + * + * @param object object to alter + * @param methodIndex field id to update + * @param value new value + */ + public abstract void set(T object, int methodIndex, Object value); + + /** + * get field value by field index + * + * @param object object to operate + * @param methodIndex field number to operate + * @return value of the field + */ + public abstract Object get(T object, int methodIndex); + + /** + * create a new targeted object + * + * @return new instance + */ + public abstract T newInstance(); + + /** + * set field value by field name + * + * @param object target object + * @param methodName methodName + * @param value new field value + */ + public void set(T object, String methodName, Object value) { + int i = getIndex(methodName); + if (i == -1) + throw new net.minidev.asm.ex.NoSuchFieldException( + methodName + " in " + object.getClass() + " to put value : " + value); + set(object, i, value); + } + + /** + * get field value by field name + * + * @param object object to operate + * @param methodName getter to call + * @return field value returned by the getter + */ + public Object get(T object, String methodName) { + return get(object, getIndex(methodName)); + } + + /** + * Returns the index of the field accessor. + * + * @param name field name + * @return id of the field + */ + public int getIndex(String name) { + Accessor ac = map.get(name); + if (ac == null) return -1; + return ac.index; + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/BeansAccessBuilder.java b/accessors-smart/src/main/java/net/minidev/asm/BeansAccessBuilder.java index 39fce9b..d4f8950 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/BeansAccessBuilder.java +++ b/accessors-smart/src/main/java/net/minidev/asm/BeansAccessBuilder.java @@ -31,7 +31,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; - import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; @@ -39,457 +38,470 @@ import org.objectweb.asm.Type; /** - * A builder class for dynamically creating {@link BeansAccess} classes for accessing bean properties efficiently. - * This class utilizes the ASM library to generate bytecode at runtime, thereby bypassing the need for Java reflection. + * A builder class for dynamically creating {@link BeansAccess} classes for accessing bean + * properties efficiently. This class utilizes the ASM library to generate bytecode at runtime, + * thereby bypassing the need for Java reflection. */ public class BeansAccessBuilder { - static private String METHOD_ACCESS_NAME = Type.getInternalName(BeansAccess.class); - - final Class type; - final Accessor[] accs; - final DynamicClassLoader loader; - final String className; - final String accessClassName; - final String accessClassNameInternal; - final String classNameInternal; - final HashMap, Method> convMtds = new HashMap, Method>(); -// Class exceptionClass = net.minidev.asm.ex.NoSuchFieldException.class; - Class exceptionClass = NoSuchFieldException.class; - - /** - * Initializes a new builder instance for a given bean class. - * - * @param type - * type to be access - * @param accs - * used accessor - * @param loader - * Loader used to store the generated class - */ - public BeansAccessBuilder(Class type, Accessor[] accs, DynamicClassLoader loader) { - this.type = type; - this.accs = accs; - this.loader = loader; - - this.className = type.getName(); - if (className.startsWith("java.")) - this.accessClassName = "net.minidev.asm." + className + "AccAccess"; - else - this.accessClassName = className.concat("AccAccess"); - - this.accessClassNameInternal = accessClassName.replace('.', '/'); - this.classNameInternal = className.replace('.', '/'); - } - /** - * register multiple new conversion - * @param conv conv list - */ - public void addConversion(Iterable> conv) { - if (conv == null) - return; - for (Class c : conv) - addConversion(c); - } - - /** - * Resister a new conversion - * @param conv the conv - */ - public void addConversion(Class conv) { - if (conv == null) - return; - for (Method mtd : conv.getMethods()) { - if ((mtd.getModifiers() & Modifier.STATIC) == 0) - continue; - Class[] param = mtd.getParameterTypes(); - if (param.length != 1) - continue; - if (!param[0].equals(Object.class)) - continue; - Class rType = mtd.getReturnType(); - if (rType.equals(Void.TYPE)) - continue; - convMtds.put(rType, mtd); - } - } - - /** - * build the conversion class. - * @return the new Class - */ - public Class bulid() { - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); - MethodVisitor mv; - - boolean USE_HASH = accs.length > 10; - int HASH_LIMIT = 14; - - String signature = "Lnet/minidev/asm/BeansAccess;"; - - cw.visit(Opcodes.V1_6, ACC_PUBLIC + Opcodes.ACC_SUPER, accessClassNameInternal, signature, METHOD_ACCESS_NAME, null); - // init - { - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, METHOD_ACCESS_NAME, "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - } - - - //////////// - // Build SETter using filed index - // - // public void set(Object object, int fieldId, Object value) - mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, null); - mv.visitCode(); - // if no Field simply return - if (accs.length == 0) { - // - // mv.visitInsn(RETURN); - } else if (accs.length > HASH_LIMIT) { - // lots of field Use Switch Statement - mv.visitVarInsn(ILOAD, 2); - Label[] labels = ASMUtil.newLabels(accs.length); - Label defaultLabel = new Label(); - - mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); - int i = 0; - for (Accessor acc : accs) { - mv.visitLabel(labels[i++]); - if (!acc.isWritable()) { - mv.visitInsn(RETURN); - continue; - } - internalSetFiled(mv, acc); - } - mv.visitLabel(defaultLabel); - } else { - Label[] labels = ASMUtil.newLabels(accs.length); - int i = 0; - for (Accessor acc : accs) { - ifNotEqJmp(mv, 2, i, labels[i]); - internalSetFiled(mv, acc); - mv.visitLabel(labels[i]); - mv.visitFrame(F_SAME, 0, null, 0, null); - i++; - } - } - if (exceptionClass != null) - throwExIntParam(mv, exceptionClass); - else - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - - //////////// - // Build GETter using filed index - // - // public Object get(Object object, int fieldId) - mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null); - mv.visitCode(); - if (accs.length == 0) { - mv.visitFrame(F_SAME, 0, null, 0, null); - } else if (accs.length > HASH_LIMIT) { - mv.visitVarInsn(ILOAD, 2); - Label[] labels = ASMUtil.newLabels(accs.length); - Label defaultLabel = new Label(); - mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); - int i = 0; - for (Accessor acc : accs) { - mv.visitLabel(labels[i++]); - mv.visitFrame(F_SAME, 0, null, 0, null); - if (!acc.isReadable()) { - mv.visitInsn(ACONST_NULL); - mv.visitInsn(ARETURN); - continue; - } - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, classNameInternal); - Type fieldType = Type.getType(acc.getType()); - if (acc.isPublic() || acc.getter == null) { - mv.visitFieldInsn(GETFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); - } else { - String sig = Type.getMethodDescriptor(acc.getter); - mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.getter.getName(), sig, false); - } - ASMUtil.autoBoxing(mv, fieldType); - mv.visitInsn(ARETURN); - } - mv.visitLabel(defaultLabel); - mv.visitFrame(F_SAME, 0, null, 0, null); - } else { - Label[] labels = ASMUtil.newLabels(accs.length); - int i = 0; - for (Accessor acc : accs) { - ifNotEqJmp(mv, 2, i, labels[i]); - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, classNameInternal); - Type fieldType = Type.getType(acc.getType()); - if (acc.isPublic() || acc.getter == null) { - mv.visitFieldInsn(GETFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); - } else { - if (acc.getter == null) - throw new RuntimeException("no Getter for field " + acc.getName() + " in class " + this.className); - String sig = Type.getMethodDescriptor(acc.getter); - mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.getter.getName(), sig, false); - } - ASMUtil.autoBoxing(mv, fieldType); - mv.visitInsn(ARETURN); - - mv.visitLabel(labels[i]); - mv.visitFrame(F_SAME, 0, null, 0, null); - i++; - } - } - - if (exceptionClass != null) - throwExIntParam(mv, exceptionClass); - else { - mv.visitInsn(ACONST_NULL); - mv.visitInsn(ARETURN); - } - mv.visitMaxs(0, 0); - mv.visitEnd(); - - - //////////// - // Build SETter using filed Name - // - // public Object set(Object object, String methodName, Object value) - if (!USE_HASH) { - mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", null, null); - mv.visitCode(); - - Label[] labels = ASMUtil.newLabels(accs.length); - - int i = 0; - for (Accessor acc : accs) { - mv.visitVarInsn(ALOAD, 2); - mv.visitLdcInsn(acc.fieldName); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); - mv.visitJumpInsn(IFEQ, labels[i]); - internalSetFiled(mv, acc); - mv.visitLabel(labels[i]); - mv.visitFrame(F_SAME, 0, null, 0, null); - i++; - } - if (exceptionClass != null) - throwExStrParam(mv, exceptionClass); - else - mv.visitInsn(RETURN); - mv.visitMaxs(0, 0); // 2,4 - mv.visitEnd(); - } - - //////////// - // Build GETter using filed Name - // - // public Object get(Object object, String methodName) - if (!USE_HASH) { - mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", null, null); - mv.visitCode(); - - Label[] labels = ASMUtil.newLabels(accs.length); - - int i = 0; - for (Accessor acc : accs) { - mv.visitVarInsn(ALOAD, 2); // methodName - mv.visitLdcInsn(acc.fieldName); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); - mv.visitJumpInsn(IFEQ, labels[i]); - mv.visitVarInsn(ALOAD, 1); // object - mv.visitTypeInsn(CHECKCAST, classNameInternal); - Type fieldType = Type.getType(acc.getType()); - if (acc.isPublic() || acc.getter == null) { - mv.visitFieldInsn(GETFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); - } else { - String sig = Type.getMethodDescriptor(acc.getter); - mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.getter.getName(), sig, false); - } - ASMUtil.autoBoxing(mv, fieldType); - mv.visitInsn(ARETURN); - mv.visitLabel(labels[i]); - mv.visitFrame(F_SAME, 0, null, 0, null); - i++; - } - if (exceptionClass != null) - throwExStrParam(mv, exceptionClass); - else { - mv.visitInsn(ACONST_NULL); - mv.visitInsn(ARETURN); - } - mv.visitMaxs(0, 0); - mv.visitEnd(); - } - - //////////// - // Build constructor - // - - { - mv = cw.visitMethod(ACC_PUBLIC, "newInstance", "()Ljava/lang/Object;", null, null); - mv.visitCode(); - mv.visitTypeInsn(NEW, classNameInternal); - mv.visitInsn(DUP); - mv.visitMethodInsn(INVOKESPECIAL, classNameInternal, "", "()V", false); - mv.visitInsn(ARETURN); - mv.visitMaxs(2, 1); - mv.visitEnd(); - } - cw.visitEnd(); - byte[] data = cw.toByteArray(); - // dumpDebug(data, "/tmp/debug-" + accessClassName + ".txt"); - return loader.defineClass(accessClassName, data); - } - - /** - * Dump Generate Code - */ - @SuppressWarnings("unused") - private void dumpDebug(byte[] data, String destFile) { - // try { - // File debug = new File(destFile); - // int flags = ClassReader.SKIP_DEBUG; - // ClassReader cr = new ClassReader(new ByteArrayInputStream(data)); - // cr.accept(new ASMifierClassVisitor(new PrintWriter(debug)), - // ASMifierClassVisitor.getDefaultAttributes(), - // flags); - // } catch (Exception e) { - // } - } - - /** - * Dump Set Field Code - * - * @param mv - * @param acc - */ - private void internalSetFiled(MethodVisitor mv, Accessor acc) { - /** - * FNC params - * - * 1 -> object to alter - * - * 2 -> id of field - * - * 3 -> new value - */ - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, classNameInternal); - // get VALUE - mv.visitVarInsn(ALOAD, 3); - Type fieldType = Type.getType(acc.getType()); - Class type = acc.getType(); - String destClsName = Type.getInternalName(type); - - Method conMtd = convMtds.get(type); - if (conMtd != null) { - // external conversion - String clsSig = Type.getInternalName(conMtd.getDeclaringClass()); - String mtdName = conMtd.getName(); - String mtdSig = Type.getMethodDescriptor(conMtd); - mv.visitMethodInsn(INVOKESTATIC, clsSig, mtdName, mtdSig, false); - } else if (acc.isEnum()) { - // builtIn Enum Conversion - Label isNull = new Label(); - mv.visitJumpInsn(IFNULL, isNull); - mv.visitVarInsn(ALOAD, 3); - // mv.visitTypeInsn(CHECKCAST, "java/lang/String"); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); - mv.visitMethodInsn(INVOKESTATIC, destClsName, "valueOf", "(Ljava/lang/String;)L" + destClsName + ";", false); - mv.visitVarInsn(ASTORE, 3); - mv.visitLabel(isNull); - mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, this.classNameInternal); // "net/minidev/asm/bean/BEnumPriv" - mv.visitVarInsn(ALOAD, 3); - mv.visitTypeInsn(CHECKCAST, destClsName); - } else if (type.equals(String.class)) { - // built In String Conversion - Label isNull = new Label(); - mv.visitJumpInsn(IFNULL, isNull); - mv.visitVarInsn(ALOAD, 3); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); - mv.visitVarInsn(ASTORE, 3); - mv.visitLabel(isNull); - mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); - mv.visitVarInsn(ALOAD, 1); - mv.visitTypeInsn(CHECKCAST, this.classNameInternal); - mv.visitVarInsn(ALOAD, 3); - mv.visitTypeInsn(CHECKCAST, destClsName); - } else { - // just check Cast - mv.visitTypeInsn(CHECKCAST, destClsName); - } - if (acc.isPublic() || acc.setter == null) { - mv.visitFieldInsn(PUTFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); - } else { - String sig = Type.getMethodDescriptor(acc.setter); - mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.setter.getName(), sig, false); - } - mv.visitInsn(RETURN); - } - - /** - * add Throws statement with int param 2 - */ - private void throwExIntParam(MethodVisitor mv, Class exCls) { - String exSig = Type.getInternalName(exCls); - mv.visitTypeInsn(NEW, exSig); - mv.visitInsn(DUP); - mv.visitLdcInsn("mapping " + this.className + " failed to map field:"); - mv.visitVarInsn(ILOAD, 2); - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "toString", "(I)Ljava/lang/String;", false); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "concat", "(Ljava/lang/String;)Ljava/lang/String;", false); - mv.visitMethodInsn(INVOKESPECIAL, exSig, "", "(Ljava/lang/String;)V", false); - mv.visitInsn(ATHROW); - } - - /** - * add Throws statement with String param 2 - */ - private void throwExStrParam(MethodVisitor mv, Class exCls) { - String exSig = Type.getInternalName(exCls); - mv.visitTypeInsn(NEW, exSig); - mv.visitInsn(DUP); - mv.visitLdcInsn("mapping " + this.className + " failed to map field:"); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "concat", "(Ljava/lang/String;)Ljava/lang/String;", false); - mv.visitMethodInsn(INVOKESPECIAL, exSig, "", "(Ljava/lang/String;)V", false); - mv.visitInsn(ATHROW); - } - - /** - * dump a Jump if not EQ - */ - private void ifNotEqJmp(MethodVisitor mv, int param, int value, Label label) { - mv.visitVarInsn(ILOAD, param); - if (value == 0) { - /* notest for value 0 */ - mv.visitJumpInsn(IFNE, label); - } else if (value == 1) { - mv.visitInsn(ICONST_1); - mv.visitJumpInsn(IF_ICMPNE, label); - } else if (value == 2) { - mv.visitInsn(ICONST_2); - mv.visitJumpInsn(IF_ICMPNE, label); - } else if (value == 3) { - mv.visitInsn(ICONST_3); - mv.visitJumpInsn(IF_ICMPNE, label); - } else if (value == 4) { - mv.visitInsn(ICONST_4); - mv.visitJumpInsn(IF_ICMPNE, label); - } else if (value == 5) { - mv.visitInsn(ICONST_5); - mv.visitJumpInsn(IF_ICMPNE, label); - } else if (value >= 6) { - mv.visitIntInsn(BIPUSH, value); - mv.visitJumpInsn(IF_ICMPNE, label); - } else { - throw new RuntimeException("non supported negative values"); - } - } + private static String METHOD_ACCESS_NAME = Type.getInternalName(BeansAccess.class); + + final Class type; + final Accessor[] accs; + final DynamicClassLoader loader; + final String className; + final String accessClassName; + final String accessClassNameInternal; + final String classNameInternal; + final HashMap, Method> convMtds = new HashMap, Method>(); + // Class exceptionClass = net.minidev.asm.ex.NoSuchFieldException.class; + Class exceptionClass = NoSuchFieldException.class; + + /** + * Initializes a new builder instance for a given bean class. + * + * @param type type to be access + * @param accs used accessor + * @param loader Loader used to store the generated class + */ + public BeansAccessBuilder(Class type, Accessor[] accs, DynamicClassLoader loader) { + this.type = type; + this.accs = accs; + this.loader = loader; + + this.className = type.getName(); + if (className.startsWith("java.")) + this.accessClassName = "net.minidev.asm." + className + "AccAccess"; + else this.accessClassName = className.concat("AccAccess"); + + this.accessClassNameInternal = accessClassName.replace('.', '/'); + this.classNameInternal = className.replace('.', '/'); + } + + /** + * register multiple new conversion + * + * @param conv conv list + */ + public void addConversion(Iterable> conv) { + if (conv == null) return; + for (Class c : conv) addConversion(c); + } + + /** + * Resister a new conversion + * + * @param conv the conv + */ + public void addConversion(Class conv) { + if (conv == null) return; + for (Method mtd : conv.getMethods()) { + if ((mtd.getModifiers() & Modifier.STATIC) == 0) continue; + Class[] param = mtd.getParameterTypes(); + if (param.length != 1) continue; + if (!param[0].equals(Object.class)) continue; + Class rType = mtd.getReturnType(); + if (rType.equals(Void.TYPE)) continue; + convMtds.put(rType, mtd); + } + } + + /** + * build the conversion class. + * + * @return the new Class + */ + public Class bulid() { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + MethodVisitor mv; + + boolean USE_HASH = accs.length > 10; + int HASH_LIMIT = 14; + + String signature = "Lnet/minidev/asm/BeansAccess;"; + + cw.visit( + Opcodes.V1_6, + ACC_PUBLIC + Opcodes.ACC_SUPER, + accessClassNameInternal, + signature, + METHOD_ACCESS_NAME, + null); + // init + { + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, METHOD_ACCESS_NAME, "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + //////////// + // Build SETter using filed index + // + // public void set(Object object, int fieldId, Object value) + mv = cw.visitMethod(ACC_PUBLIC, "set", "(Ljava/lang/Object;ILjava/lang/Object;)V", null, null); + mv.visitCode(); + // if no Field simply return + if (accs.length == 0) { + // + // mv.visitInsn(RETURN); + } else if (accs.length > HASH_LIMIT) { + // lots of field Use Switch Statement + mv.visitVarInsn(ILOAD, 2); + Label[] labels = ASMUtil.newLabels(accs.length); + Label defaultLabel = new Label(); + + mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); + int i = 0; + for (Accessor acc : accs) { + mv.visitLabel(labels[i++]); + if (!acc.isWritable()) { + mv.visitInsn(RETURN); + continue; + } + internalSetFiled(mv, acc); + } + mv.visitLabel(defaultLabel); + } else { + Label[] labels = ASMUtil.newLabels(accs.length); + int i = 0; + for (Accessor acc : accs) { + ifNotEqJmp(mv, 2, i, labels[i]); + internalSetFiled(mv, acc); + mv.visitLabel(labels[i]); + mv.visitFrame(F_SAME, 0, null, 0, null); + i++; + } + } + if (exceptionClass != null) throwExIntParam(mv, exceptionClass); + else mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + + //////////// + // Build GETter using filed index + // + // public Object get(Object object, int fieldId) + mv = cw.visitMethod(ACC_PUBLIC, "get", "(Ljava/lang/Object;I)Ljava/lang/Object;", null, null); + mv.visitCode(); + if (accs.length == 0) { + mv.visitFrame(F_SAME, 0, null, 0, null); + } else if (accs.length > HASH_LIMIT) { + mv.visitVarInsn(ILOAD, 2); + Label[] labels = ASMUtil.newLabels(accs.length); + Label defaultLabel = new Label(); + mv.visitTableSwitchInsn(0, labels.length - 1, defaultLabel, labels); + int i = 0; + for (Accessor acc : accs) { + mv.visitLabel(labels[i++]); + mv.visitFrame(F_SAME, 0, null, 0, null); + if (!acc.isReadable()) { + mv.visitInsn(ACONST_NULL); + mv.visitInsn(ARETURN); + continue; + } + mv.visitVarInsn(ALOAD, 1); + mv.visitTypeInsn(CHECKCAST, classNameInternal); + Type fieldType = Type.getType(acc.getType()); + if (acc.isPublic() || acc.getter == null) { + mv.visitFieldInsn(GETFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); + } else { + String sig = Type.getMethodDescriptor(acc.getter); + mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.getter.getName(), sig, false); + } + ASMUtil.autoBoxing(mv, fieldType); + mv.visitInsn(ARETURN); + } + mv.visitLabel(defaultLabel); + mv.visitFrame(F_SAME, 0, null, 0, null); + } else { + Label[] labels = ASMUtil.newLabels(accs.length); + int i = 0; + for (Accessor acc : accs) { + ifNotEqJmp(mv, 2, i, labels[i]); + mv.visitVarInsn(ALOAD, 1); + mv.visitTypeInsn(CHECKCAST, classNameInternal); + Type fieldType = Type.getType(acc.getType()); + if (acc.isPublic() || acc.getter == null) { + mv.visitFieldInsn(GETFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); + } else { + if (acc.getter == null) + throw new RuntimeException( + "no Getter for field " + acc.getName() + " in class " + this.className); + String sig = Type.getMethodDescriptor(acc.getter); + mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.getter.getName(), sig, false); + } + ASMUtil.autoBoxing(mv, fieldType); + mv.visitInsn(ARETURN); + + mv.visitLabel(labels[i]); + mv.visitFrame(F_SAME, 0, null, 0, null); + i++; + } + } + + if (exceptionClass != null) throwExIntParam(mv, exceptionClass); + else { + mv.visitInsn(ACONST_NULL); + mv.visitInsn(ARETURN); + } + mv.visitMaxs(0, 0); + mv.visitEnd(); + + //////////// + // Build SETter using filed Name + // + // public Object set(Object object, String methodName, Object value) + if (!USE_HASH) { + mv = + cw.visitMethod( + ACC_PUBLIC, + "set", + "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", + null, + null); + mv.visitCode(); + + Label[] labels = ASMUtil.newLabels(accs.length); + + int i = 0; + for (Accessor acc : accs) { + mv.visitVarInsn(ALOAD, 2); + mv.visitLdcInsn(acc.fieldName); + mv.visitMethodInsn( + INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); + mv.visitJumpInsn(IFEQ, labels[i]); + internalSetFiled(mv, acc); + mv.visitLabel(labels[i]); + mv.visitFrame(F_SAME, 0, null, 0, null); + i++; + } + if (exceptionClass != null) throwExStrParam(mv, exceptionClass); + else mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); // 2,4 + mv.visitEnd(); + } + + //////////// + // Build GETter using filed Name + // + // public Object get(Object object, String methodName) + if (!USE_HASH) { + mv = + cw.visitMethod( + ACC_PUBLIC, + "get", + "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", + null, + null); + mv.visitCode(); + + Label[] labels = ASMUtil.newLabels(accs.length); + + int i = 0; + for (Accessor acc : accs) { + mv.visitVarInsn(ALOAD, 2); // methodName + mv.visitLdcInsn(acc.fieldName); + mv.visitMethodInsn( + INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); + mv.visitJumpInsn(IFEQ, labels[i]); + mv.visitVarInsn(ALOAD, 1); // object + mv.visitTypeInsn(CHECKCAST, classNameInternal); + Type fieldType = Type.getType(acc.getType()); + if (acc.isPublic() || acc.getter == null) { + mv.visitFieldInsn(GETFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); + } else { + String sig = Type.getMethodDescriptor(acc.getter); + mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.getter.getName(), sig, false); + } + ASMUtil.autoBoxing(mv, fieldType); + mv.visitInsn(ARETURN); + mv.visitLabel(labels[i]); + mv.visitFrame(F_SAME, 0, null, 0, null); + i++; + } + if (exceptionClass != null) throwExStrParam(mv, exceptionClass); + else { + mv.visitInsn(ACONST_NULL); + mv.visitInsn(ARETURN); + } + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + //////////// + // Build constructor + // + + { + mv = cw.visitMethod(ACC_PUBLIC, "newInstance", "()Ljava/lang/Object;", null, null); + mv.visitCode(); + mv.visitTypeInsn(NEW, classNameInternal); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, classNameInternal, "", "()V", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + cw.visitEnd(); + byte[] data = cw.toByteArray(); + // dumpDebug(data, "/tmp/debug-" + accessClassName + ".txt"); + return loader.defineClass(accessClassName, data); + } + + /** Dump Generate Code */ + @SuppressWarnings("unused") + private void dumpDebug(byte[] data, String destFile) { + // try { + // File debug = new File(destFile); + // int flags = ClassReader.SKIP_DEBUG; + // ClassReader cr = new ClassReader(new ByteArrayInputStream(data)); + // cr.accept(new ASMifierClassVisitor(new PrintWriter(debug)), + // ASMifierClassVisitor.getDefaultAttributes(), + // flags); + // } catch (Exception e) { + // } + } + + /** + * Dump Set Field Code + * + * @param mv + * @param acc + */ + private void internalSetFiled(MethodVisitor mv, Accessor acc) { + /** + * FNC params + * + *

1 -> object to alter + * + *

2 -> id of field + * + *

3 -> new value + */ + mv.visitVarInsn(ALOAD, 1); + mv.visitTypeInsn(CHECKCAST, classNameInternal); + // get VALUE + mv.visitVarInsn(ALOAD, 3); + Type fieldType = Type.getType(acc.getType()); + Class type = acc.getType(); + String destClsName = Type.getInternalName(type); + + Method conMtd = convMtds.get(type); + if (conMtd != null) { + // external conversion + String clsSig = Type.getInternalName(conMtd.getDeclaringClass()); + String mtdName = conMtd.getName(); + String mtdSig = Type.getMethodDescriptor(conMtd); + mv.visitMethodInsn(INVOKESTATIC, clsSig, mtdName, mtdSig, false); + } else if (acc.isEnum()) { + // builtIn Enum Conversion + Label isNull = new Label(); + mv.visitJumpInsn(IFNULL, isNull); + mv.visitVarInsn(ALOAD, 3); + // mv.visitTypeInsn(CHECKCAST, "java/lang/String"); + mv.visitMethodInsn( + INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); + mv.visitMethodInsn( + INVOKESTATIC, destClsName, "valueOf", "(Ljava/lang/String;)L" + destClsName + ";", false); + mv.visitVarInsn(ASTORE, 3); + mv.visitLabel(isNull); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + mv.visitVarInsn(ALOAD, 1); + mv.visitTypeInsn(CHECKCAST, this.classNameInternal); // "net/minidev/asm/bean/BEnumPriv" + mv.visitVarInsn(ALOAD, 3); + mv.visitTypeInsn(CHECKCAST, destClsName); + } else if (type.equals(String.class)) { + // built In String Conversion + Label isNull = new Label(); + mv.visitJumpInsn(IFNULL, isNull); + mv.visitVarInsn(ALOAD, 3); + mv.visitMethodInsn( + INVOKEVIRTUAL, "java/lang/Object", "toString", "()Ljava/lang/String;", false); + mv.visitVarInsn(ASTORE, 3); + mv.visitLabel(isNull); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + mv.visitVarInsn(ALOAD, 1); + mv.visitTypeInsn(CHECKCAST, this.classNameInternal); + mv.visitVarInsn(ALOAD, 3); + mv.visitTypeInsn(CHECKCAST, destClsName); + } else { + // just check Cast + mv.visitTypeInsn(CHECKCAST, destClsName); + } + if (acc.isPublic() || acc.setter == null) { + mv.visitFieldInsn(PUTFIELD, classNameInternal, acc.getName(), fieldType.getDescriptor()); + } else { + String sig = Type.getMethodDescriptor(acc.setter); + mv.visitMethodInsn(INVOKEVIRTUAL, classNameInternal, acc.setter.getName(), sig, false); + } + mv.visitInsn(RETURN); + } + + /** add Throws statement with int param 2 */ + private void throwExIntParam(MethodVisitor mv, Class exCls) { + String exSig = Type.getInternalName(exCls); + mv.visitTypeInsn(NEW, exSig); + mv.visitInsn(DUP); + mv.visitLdcInsn("mapping " + this.className + " failed to map field:"); + mv.visitVarInsn(ILOAD, 2); + mv.visitMethodInsn( + INVOKESTATIC, "java/lang/Integer", "toString", "(I)Ljava/lang/String;", false); + mv.visitMethodInsn( + INVOKEVIRTUAL, + "java/lang/String", + "concat", + "(Ljava/lang/String;)Ljava/lang/String;", + false); + mv.visitMethodInsn(INVOKESPECIAL, exSig, "", "(Ljava/lang/String;)V", false); + mv.visitInsn(ATHROW); + } + + /** add Throws statement with String param 2 */ + private void throwExStrParam(MethodVisitor mv, Class exCls) { + String exSig = Type.getInternalName(exCls); + mv.visitTypeInsn(NEW, exSig); + mv.visitInsn(DUP); + mv.visitLdcInsn("mapping " + this.className + " failed to map field:"); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn( + INVOKEVIRTUAL, + "java/lang/String", + "concat", + "(Ljava/lang/String;)Ljava/lang/String;", + false); + mv.visitMethodInsn(INVOKESPECIAL, exSig, "", "(Ljava/lang/String;)V", false); + mv.visitInsn(ATHROW); + } + + /** dump a Jump if not EQ */ + private void ifNotEqJmp(MethodVisitor mv, int param, int value, Label label) { + mv.visitVarInsn(ILOAD, param); + if (value == 0) { + /* notest for value 0 */ + mv.visitJumpInsn(IFNE, label); + } else if (value == 1) { + mv.visitInsn(ICONST_1); + mv.visitJumpInsn(IF_ICMPNE, label); + } else if (value == 2) { + mv.visitInsn(ICONST_2); + mv.visitJumpInsn(IF_ICMPNE, label); + } else if (value == 3) { + mv.visitInsn(ICONST_3); + mv.visitJumpInsn(IF_ICMPNE, label); + } else if (value == 4) { + mv.visitInsn(ICONST_4); + mv.visitJumpInsn(IF_ICMPNE, label); + } else if (value == 5) { + mv.visitInsn(ICONST_5); + mv.visitJumpInsn(IF_ICMPNE, label); + } else if (value >= 6) { + mv.visitIntInsn(BIPUSH, value); + mv.visitJumpInsn(IF_ICMPNE, label); + } else { + throw new RuntimeException("non supported negative values"); + } + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/BeansAccessConfig.java b/accessors-smart/src/main/java/net/minidev/asm/BeansAccessConfig.java index 2564c6d..2302c31 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/BeansAccessConfig.java +++ b/accessors-smart/src/main/java/net/minidev/asm/BeansAccessConfig.java @@ -3,84 +3,80 @@ import java.util.HashMap; import java.util.LinkedHashSet; -/** - * Beans Access Config - */ +/** Beans Access Config */ public class BeansAccessConfig { - /** - * default constructor - */ - public BeansAccessConfig() { - super(); - } - /** - * Field type convertor for all classes - * - * Convertor classes should contains mapping method Prototyped as: - * - * public static DestinationType Method(Object data); - * - * @see DefaultConverter - */ - //static protected LinkedHashSet> globalMapper = new LinkedHashSet>(); + /** default constructor */ + public BeansAccessConfig() { + super(); + } - /** - * Field type convertor for custom Class - * - * Convertor classes should contains mapping method Prototyped as: - * - * public static DestinationType Method(Object data); - * - * @see DefaultConverter - */ - static protected HashMap, LinkedHashSet>> classMapper = new HashMap, LinkedHashSet>>(); + /** + * Field type convertor for all classes + * + *

Convertor classes should contains mapping method Prototyped as: + * + *

public static DestinationType Method(Object data); + * + * @see DefaultConverter + */ + // static protected LinkedHashSet> globalMapper = new LinkedHashSet>(); - /** - * FiledName remapper for a specific class or interface - */ - static protected HashMap, HashMap> classFiledNameMapper = new HashMap, HashMap>(); + /** + * Field type convertor for custom Class + * + *

Convertor classes should contains mapping method Prototyped as: + * + *

public static DestinationType Method(Object data); + * + * @see DefaultConverter + */ + protected static HashMap, LinkedHashSet>> classMapper = + new HashMap, LinkedHashSet>>(); - static { - addTypeMapper(Object.class, DefaultConverter.class); - addTypeMapper(Object.class, ConvertDate.class); - } + /** FiledName remapper for a specific class or interface */ + protected static HashMap, HashMap> classFiledNameMapper = + new HashMap, HashMap>(); -// /** -// * Field type convertor for all classes -// * -// * Convertor classes should contains mapping method Prototyped as: -// * -// * public static DestinationType Method(Object data); -// * -// * @see DefaultConverter -// */ -// public static void addGlobalTypeMapper(Class mapper) { -// synchronized (globalMapper) { -// globalMapper.add(mapper); -// } -// } + static { + addTypeMapper(Object.class, DefaultConverter.class); + addTypeMapper(Object.class, ConvertDate.class); + } - /** - * Field type convertor for all classes - * - * Convertor classes should contains mapping method Prototyped as: - * - * public static DestinationType Method(Object data); - * - * @see DefaultConverter - * - * @param clz class - * @param mapper mapper - */ - public static void addTypeMapper(Class clz, Class mapper) { - synchronized (classMapper) { - LinkedHashSet> h = classMapper.get(clz); - if (h == null) { - h = new LinkedHashSet>(); - classMapper.put(clz, h); - } - - h.add(mapper); - } - } + // /** + // * Field type convertor for all classes + // * + // * Convertor classes should contains mapping method Prototyped as: + // * + // * public static DestinationType Method(Object data); + // * + // * @see DefaultConverter + // */ + // public static void addGlobalTypeMapper(Class mapper) { + // synchronized (globalMapper) { + // globalMapper.add(mapper); + // } + // } + + /** + * Field type convertor for all classes + * + *

Convertor classes should contains mapping method Prototyped as: + * + *

public static DestinationType Method(Object data); + * + * @see DefaultConverter + * @param clz class + * @param mapper mapper + */ + public static void addTypeMapper(Class clz, Class mapper) { + synchronized (classMapper) { + LinkedHashSet> h = classMapper.get(clz); + if (h == null) { + h = new LinkedHashSet>(); + classMapper.put(clz, h); + } + + h.add(mapper); + } + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/ConvertDate.java b/accessors-smart/src/main/java/net/minidev/asm/ConvertDate.java index a629133..3b36c45 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/ConvertDate.java +++ b/accessors-smart/src/main/java/net/minidev/asm/ConvertDate.java @@ -12,396 +12,359 @@ import java.util.TreeMap; /** - * Utility class for converting strings into {@link Date} objects, considering various global date formats. - * It handles different month and day names across languages, and supports timezone adjustments. + * Utility class for converting strings into {@link Date} objects, considering various global date + * formats. It handles different month and day names across languages, and supports timezone + * adjustments. */ public class ConvertDate { - /** - * default constructor - */ - public ConvertDate() { - super(); - } - static TreeMap monthsTable = new TreeMap(new StringCmpNS()); // StringCmpNS.COMP - static TreeMap daysTable = new TreeMap(new StringCmpNS()); // StringCmpNS.COMP - private static HashSet voidData = new HashSet(); - /** - * Default TimeZone used for date conversions. Can be overwritten to change the default time zone. - */ - public static TimeZone defaultTimeZone; - /** - * Comparator for case-insensitive string comparison. Used for sorting and comparing month and day names. - */ - public static class StringCmpNS implements Comparator { - /** - * default constructor - */ - public StringCmpNS() { - super(); - } - - @Override - public int compare(String o1, String o2) { - return o1.compareToIgnoreCase(o2); - } - } - - /** - * Retrieves the month's integer representation based on the provided month name. - * - * @param month the name of the month - * @return the integer value of the month, or null if the month name is unrecognized - */ - public static Integer getMonth(String month) { - return monthsTable.get(month); - } - - private static Integer parseMonth(String s1) { - if (Character.isDigit(s1.charAt(0))) { - return Integer.parseInt(s1) - 1; - } else { - Integer month = monthsTable.get(s1); - if (month == null) - throw new NullPointerException("can not parse " + s1 + " as month"); - return month.intValue(); - } - } - - /** - * @return a current timezoned 01/01/2000 00:00:00 GregorianCalendar - */ - private static GregorianCalendar newCalandar() { - GregorianCalendar cal = new GregorianCalendar(2000, 0, 0, 0, 0, 0); - if (defaultTimeZone != null) - cal.setTimeZone(defaultTimeZone); - TimeZone TZ = cal.getTimeZone(); - if (TZ == null) { - TZ = TimeZone.getDefault(); - } - cal.setTimeInMillis(-TZ.getRawOffset()); - return cal; - } - - static TreeMap timeZoneMapping; - static { - timeZoneMapping = new TreeMap(); - voidData.add("à"); // added for french 1st of may 2021 - voidData.add("at"); - voidData.add("MEZ"); - voidData.add("Uhr"); - voidData.add("h"); - voidData.add("pm"); - voidData.add("PM"); - voidData.add("am"); - voidData.add("AM"); - voidData.add("min"); // Canada french - voidData.add("um"); // German - voidData.add("o'clock"); - - for (String tz : TimeZone.getAvailableIDs()) { - timeZoneMapping.put(tz, TimeZone.getTimeZone(tz)); - } - - for (Locale locale : DateFormatSymbols.getAvailableLocales()) { - if ("ja".equals(locale.getLanguage())) - continue; - if ("ko".equals(locale.getLanguage())) - continue; - if ("zh".equals(locale.getLanguage())) - continue; - DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale); - String[] keys = dfs.getMonths(); - for (int i = 0; i < keys.length; i++) { - if (keys[i].length() == 0) - continue; - fillMap(monthsTable, keys[i], Integer.valueOf(i)); - } - keys = dfs.getShortMonths(); - for (int i = 0; i < keys.length; i++) { - String s = keys[i]; - if (s.length() == 0) - continue; - if (Character.isDigit(s.charAt(s.length() - 1))) - continue; - fillMap(monthsTable, keys[i], Integer.valueOf(i)); - fillMap(monthsTable, keys[i].replace(".", ""), Integer.valueOf(i)); - } - keys = dfs.getWeekdays(); - for (int i = 0; i < keys.length; i++) { - String s = keys[i]; - if (s.length() == 0) - continue; - fillMap(daysTable, s, Integer.valueOf(i)); - fillMap(daysTable, s.replace(".", ""), Integer.valueOf(i)); - } - keys = dfs.getShortWeekdays(); - for (int i = 0; i < keys.length; i++) { - String s = keys[i]; - if (s.length() == 0) - continue; - fillMap(daysTable, s, Integer.valueOf(i)); - fillMap(daysTable, s.replace(".", ""), Integer.valueOf(i)); - } - } - } - - private static void fillMap(TreeMap map, String key, Integer value) { - map.put(key, value); - key = key.replace("é", "e"); - key = key.replace("û", "u"); - map.put(key, value); - } - - /** - * try read a Date from a Object - * @param obj object to convert to date - * @return a date value - */ - public static Date convertToDate(Object obj) { - if (obj == null) - return null; - if (obj instanceof Date) - return (Date) obj; - if (obj instanceof Number) - return new Date(((Number)obj).longValue()); - if (obj instanceof String) { - obj = ((String) obj) - .replace("p.m.", "pm") - .replace("a.m.", "am"); // added on 1st of may 2021 - // contains 2 differents spaces - StringTokenizer st = new StringTokenizer((String) obj, "  -/:,.+年月日曜時分秒"); - // 2012年1月23日月曜日 13時42分59秒 中央ヨーロッパ標準時 - String s1 = ""; - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - if (s1.length() == 4 && Character.isDigit(s1.charAt(0))) - return getYYYYMMDD(st, s1); - // skip Day if present. - if (daysTable.containsKey(s1)) { - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - } - if (monthsTable.containsKey(s1)) - return getMMDDYYYY(st, s1); - - if (Character.isDigit(s1.charAt(0))) - return getDDMMYYYY(st, s1); - return null; - } - throw new RuntimeException("Primitive: Can not convert " + obj.getClass().getName() + " to int"); - } - - /** - * - * @param st StringTokenizer - * @param s1 previous token - * @return a Date - */ - private static Date getYYYYMMDD(StringTokenizer st, String s1) { - GregorianCalendar cal = newCalandar(); - - int year = Integer.parseInt(s1); - cal.set(Calendar.YEAR, year); - if (!st.hasMoreTokens()) - return cal.getTime(); - s1 = st.nextToken(); - - cal.set(Calendar.MONTH, parseMonth(s1)); - if (!st.hasMoreTokens()) - return cal.getTime(); - - s1 = st.nextToken(); - if (Character.isDigit(s1.charAt(0))) { - if (s1.length() == 5 && s1.charAt(2) == 'T') { - // TIME + TIMEZONE - int day = Integer.parseInt(s1.substring(0,2)); - cal.set(Calendar.DAY_OF_MONTH, day); - return addHour(st, cal, s1.substring(3)); - } - int day = Integer.parseInt(s1); - cal.set(Calendar.DAY_OF_MONTH, day); - return addHour(st, cal, null); - } - return cal.getTime(); - } - - /** - * @param s1 2 years date - * @return a 1900 or 2000 year - */ - private static int getYear(String s1) { - int year = Integer.parseInt(s1); - // CET ? - if (year < 100) { - if (year > 30) - year += 2000; - else - year += 1900; - } - return year; - } - /** - * @param st StringTokenizer - * @param s1 privious token - * @return a date - */ - private static Date getMMDDYYYY(StringTokenizer st, String s1) { - GregorianCalendar cal = newCalandar(); - - Integer month = monthsTable.get(s1); - if (month == null) - throw new NullPointerException("can not parse " + s1 + " as month"); - cal.set(Calendar.MONTH, month); - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - // DAY - int day = Integer.parseInt(s1); - cal.set(Calendar.DAY_OF_MONTH, day); - - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - if (Character.isLetter(s1.charAt(0))) { - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - } - if (s1.length() == 4) - cal.set(Calendar.YEAR, getYear(s1)); - else if (s1.length() == 2) { - return addHour2(st, cal, s1); - - } - // /if (st.hasMoreTokens()) - // return null; - // s1 = st.nextToken(); - return addHour(st, cal, null); - // return cal.getTime(); - } - - /** - * parse a date as DDMMYYYY - * @param st StringTokenizer - * @param s1 previous token - * @return a Date - */ - private static Date getDDMMYYYY(StringTokenizer st, String s1) { - GregorianCalendar cal = newCalandar(); - - int day = Integer.parseInt(s1); - cal.set(Calendar.DAY_OF_MONTH, day); - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - cal.set(Calendar.MONTH, parseMonth(s1)); - - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - cal.set(Calendar.YEAR, getYear(s1)); - return addHour(st, cal, null); - } - - /** - * @param st StringTokenizer - * @param cal Calendar - * @param s1 previous token - * @return a Date - */ - private static Date addHour(StringTokenizer st, Calendar cal, String s1) { - // String s1; - if (s1 == null) { - if (!st.hasMoreTokens()) - return cal.getTime(); - s1 = st.nextToken(); - } - return addHour2(st, cal, s1); - } - - /** - * @param st StringTokenizer - * @param cal Calendar - * @param s1 previous token - * @return a Date - */ - private static Date addHour2(StringTokenizer st, Calendar cal, String s1) { - s1 = trySkip(st, s1, cal); - cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(s1)); - - if (!st.hasMoreTokens()) - return cal.getTime(); - s1 = st.nextToken(); - - s1 = trySkip(st, s1, cal); - if (s1 == null) - return cal.getTime(); - - // if (s1.equalsIgnoreCase("h")) { - // if (!st.hasMoreTokens()) - // return cal.getTime(); - // s1 = st.nextToken(); - // } - cal.set(Calendar.MINUTE, Integer.parseInt(s1)); - - if (!st.hasMoreTokens()) - return cal.getTime(); - s1 = st.nextToken(); - - s1 = trySkip(st, s1, cal); - if (s1 == null) - return cal.getTime(); - - cal.set(Calendar.SECOND, Integer.parseInt(s1)); - if (!st.hasMoreTokens()) - return cal.getTime(); - s1 = st.nextToken(); - - s1 = trySkip(st, s1, cal); - if (s1 == null) - return cal.getTime(); - // TODO ADD TIME ZONE - s1 = trySkip(st, s1, cal); - // if (s1.equalsIgnoreCase("pm")) - // cal.add(Calendar.HOUR_OF_DAY, 12); - - if (s1.length() == 4 && Character.isDigit(s1.charAt(0))) - cal.set(Calendar.YEAR, getYear(s1)); - - return cal.getTime(); - } - - /** - * Handle some Date Keyword like PST UTC am pm ... - * @param st StringTokenizer - * @param s1 previous token - * @param cal Calendar - * @return a date - */ - private static String trySkip(StringTokenizer st, String s1, Calendar cal) { - while (true) { - TimeZone tz = timeZoneMapping.get(s1); - if (tz != null) { - cal.setTimeZone(tz); - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - continue; - } - if (voidData.contains(s1)) { - if (s1.equalsIgnoreCase("pm")) - cal.add(Calendar.AM_PM, Calendar.PM); - if (s1.equalsIgnoreCase("am")) - cal.add(Calendar.AM_PM, Calendar.AM); - if (!st.hasMoreTokens()) - return null; - s1 = st.nextToken(); - continue; - } - return s1; - } - } + /** default constructor */ + public ConvertDate() { + super(); + } + static TreeMap monthsTable = + new TreeMap(new StringCmpNS()); // StringCmpNS.COMP + static TreeMap daysTable = + new TreeMap(new StringCmpNS()); // StringCmpNS.COMP + private static HashSet voidData = new HashSet(); + + /** + * Default TimeZone used for date conversions. Can be overwritten to change the default time zone. + */ + public static TimeZone defaultTimeZone; + + /** + * Comparator for case-insensitive string comparison. Used for sorting and comparing month and day + * names. + */ + public static class StringCmpNS implements Comparator { + /** default constructor */ + public StringCmpNS() { + super(); + } + + @Override + public int compare(String o1, String o2) { + return o1.compareToIgnoreCase(o2); + } + } + + /** + * Retrieves the month's integer representation based on the provided month name. + * + * @param month the name of the month + * @return the integer value of the month, or null if the month name is unrecognized + */ + public static Integer getMonth(String month) { + return monthsTable.get(month); + } + + private static Integer parseMonth(String s1) { + if (Character.isDigit(s1.charAt(0))) { + return Integer.parseInt(s1) - 1; + } else { + Integer month = monthsTable.get(s1); + if (month == null) throw new NullPointerException("can not parse " + s1 + " as month"); + return month.intValue(); + } + } + + /** + * @return a current timezoned 01/01/2000 00:00:00 GregorianCalendar + */ + private static GregorianCalendar newCalandar() { + GregorianCalendar cal = new GregorianCalendar(2000, 0, 0, 0, 0, 0); + if (defaultTimeZone != null) cal.setTimeZone(defaultTimeZone); + TimeZone TZ = cal.getTimeZone(); + if (TZ == null) { + TZ = TimeZone.getDefault(); + } + cal.setTimeInMillis(-TZ.getRawOffset()); + return cal; + } + + static TreeMap timeZoneMapping; + + static { + timeZoneMapping = new TreeMap(); + voidData.add("à"); // added for french 1st of may 2021 + voidData.add("at"); + voidData.add("MEZ"); + voidData.add("Uhr"); + voidData.add("h"); + voidData.add("pm"); + voidData.add("PM"); + voidData.add("am"); + voidData.add("AM"); + voidData.add("min"); // Canada french + voidData.add("um"); // German + voidData.add("o'clock"); + + for (String tz : TimeZone.getAvailableIDs()) { + timeZoneMapping.put(tz, TimeZone.getTimeZone(tz)); + } + + for (Locale locale : DateFormatSymbols.getAvailableLocales()) { + if ("ja".equals(locale.getLanguage())) continue; + if ("ko".equals(locale.getLanguage())) continue; + if ("zh".equals(locale.getLanguage())) continue; + DateFormatSymbols dfs = DateFormatSymbols.getInstance(locale); + String[] keys = dfs.getMonths(); + for (int i = 0; i < keys.length; i++) { + if (keys[i].length() == 0) continue; + fillMap(monthsTable, keys[i], Integer.valueOf(i)); + } + keys = dfs.getShortMonths(); + for (int i = 0; i < keys.length; i++) { + String s = keys[i]; + if (s.length() == 0) continue; + if (Character.isDigit(s.charAt(s.length() - 1))) continue; + fillMap(monthsTable, keys[i], Integer.valueOf(i)); + fillMap(monthsTable, keys[i].replace(".", ""), Integer.valueOf(i)); + } + keys = dfs.getWeekdays(); + for (int i = 0; i < keys.length; i++) { + String s = keys[i]; + if (s.length() == 0) continue; + fillMap(daysTable, s, Integer.valueOf(i)); + fillMap(daysTable, s.replace(".", ""), Integer.valueOf(i)); + } + keys = dfs.getShortWeekdays(); + for (int i = 0; i < keys.length; i++) { + String s = keys[i]; + if (s.length() == 0) continue; + fillMap(daysTable, s, Integer.valueOf(i)); + fillMap(daysTable, s.replace(".", ""), Integer.valueOf(i)); + } + } + } + + private static void fillMap(TreeMap map, String key, Integer value) { + map.put(key, value); + key = key.replace("é", "e"); + key = key.replace("û", "u"); + map.put(key, value); + } + + /** + * try read a Date from a Object + * + * @param obj object to convert to date + * @return a date value + */ + public static Date convertToDate(Object obj) { + if (obj == null) return null; + if (obj instanceof Date) return (Date) obj; + if (obj instanceof Number) return new Date(((Number) obj).longValue()); + if (obj instanceof String) { + obj = ((String) obj).replace("p.m.", "pm").replace("a.m.", "am"); // added on 1st of may 2021 + // contains 2 differents spaces + StringTokenizer st = new StringTokenizer((String) obj, "  -/:,.+年月日曜時分秒"); + // 2012年1月23日月曜日 13時42分59秒 中央ヨーロッパ標準時 + String s1 = ""; + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + if (s1.length() == 4 && Character.isDigit(s1.charAt(0))) return getYYYYMMDD(st, s1); + // skip Day if present. + if (daysTable.containsKey(s1)) { + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + } + if (monthsTable.containsKey(s1)) return getMMDDYYYY(st, s1); + + if (Character.isDigit(s1.charAt(0))) return getDDMMYYYY(st, s1); + return null; + } + throw new RuntimeException( + "Primitive: Can not convert " + obj.getClass().getName() + " to int"); + } + + /** + * @param st StringTokenizer + * @param s1 previous token + * @return a Date + */ + private static Date getYYYYMMDD(StringTokenizer st, String s1) { + GregorianCalendar cal = newCalandar(); + + int year = Integer.parseInt(s1); + cal.set(Calendar.YEAR, year); + if (!st.hasMoreTokens()) return cal.getTime(); + s1 = st.nextToken(); + + cal.set(Calendar.MONTH, parseMonth(s1)); + if (!st.hasMoreTokens()) return cal.getTime(); + + s1 = st.nextToken(); + if (Character.isDigit(s1.charAt(0))) { + if (s1.length() == 5 && s1.charAt(2) == 'T') { + // TIME + TIMEZONE + int day = Integer.parseInt(s1.substring(0, 2)); + cal.set(Calendar.DAY_OF_MONTH, day); + return addHour(st, cal, s1.substring(3)); + } + int day = Integer.parseInt(s1); + cal.set(Calendar.DAY_OF_MONTH, day); + return addHour(st, cal, null); + } + return cal.getTime(); + } + + /** + * @param s1 2 years date + * @return a 1900 or 2000 year + */ + private static int getYear(String s1) { + int year = Integer.parseInt(s1); + // CET ? + if (year < 100) { + if (year > 30) year += 2000; + else year += 1900; + } + return year; + } + + /** + * @param st StringTokenizer + * @param s1 privious token + * @return a date + */ + private static Date getMMDDYYYY(StringTokenizer st, String s1) { + GregorianCalendar cal = newCalandar(); + + Integer month = monthsTable.get(s1); + if (month == null) throw new NullPointerException("can not parse " + s1 + " as month"); + cal.set(Calendar.MONTH, month); + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + // DAY + int day = Integer.parseInt(s1); + cal.set(Calendar.DAY_OF_MONTH, day); + + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + if (Character.isLetter(s1.charAt(0))) { + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + } + if (s1.length() == 4) cal.set(Calendar.YEAR, getYear(s1)); + else if (s1.length() == 2) { + return addHour2(st, cal, s1); + } + // /if (st.hasMoreTokens()) + // return null; + // s1 = st.nextToken(); + return addHour(st, cal, null); + // return cal.getTime(); + } + + /** + * parse a date as DDMMYYYY + * + * @param st StringTokenizer + * @param s1 previous token + * @return a Date + */ + private static Date getDDMMYYYY(StringTokenizer st, String s1) { + GregorianCalendar cal = newCalandar(); + + int day = Integer.parseInt(s1); + cal.set(Calendar.DAY_OF_MONTH, day); + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + cal.set(Calendar.MONTH, parseMonth(s1)); + + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + cal.set(Calendar.YEAR, getYear(s1)); + return addHour(st, cal, null); + } + + /** + * @param st StringTokenizer + * @param cal Calendar + * @param s1 previous token + * @return a Date + */ + private static Date addHour(StringTokenizer st, Calendar cal, String s1) { + // String s1; + if (s1 == null) { + if (!st.hasMoreTokens()) return cal.getTime(); + s1 = st.nextToken(); + } + return addHour2(st, cal, s1); + } + + /** + * @param st StringTokenizer + * @param cal Calendar + * @param s1 previous token + * @return a Date + */ + private static Date addHour2(StringTokenizer st, Calendar cal, String s1) { + s1 = trySkip(st, s1, cal); + cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(s1)); + + if (!st.hasMoreTokens()) return cal.getTime(); + s1 = st.nextToken(); + + s1 = trySkip(st, s1, cal); + if (s1 == null) return cal.getTime(); + + // if (s1.equalsIgnoreCase("h")) { + // if (!st.hasMoreTokens()) + // return cal.getTime(); + // s1 = st.nextToken(); + // } + cal.set(Calendar.MINUTE, Integer.parseInt(s1)); + + if (!st.hasMoreTokens()) return cal.getTime(); + s1 = st.nextToken(); + + s1 = trySkip(st, s1, cal); + if (s1 == null) return cal.getTime(); + + cal.set(Calendar.SECOND, Integer.parseInt(s1)); + if (!st.hasMoreTokens()) return cal.getTime(); + s1 = st.nextToken(); + + s1 = trySkip(st, s1, cal); + if (s1 == null) return cal.getTime(); + // TODO ADD TIME ZONE + s1 = trySkip(st, s1, cal); + // if (s1.equalsIgnoreCase("pm")) + // cal.add(Calendar.HOUR_OF_DAY, 12); + + if (s1.length() == 4 && Character.isDigit(s1.charAt(0))) cal.set(Calendar.YEAR, getYear(s1)); + + return cal.getTime(); + } + + /** + * Handle some Date Keyword like PST UTC am pm ... + * + * @param st StringTokenizer + * @param s1 previous token + * @param cal Calendar + * @return a date + */ + private static String trySkip(StringTokenizer st, String s1, Calendar cal) { + while (true) { + TimeZone tz = timeZoneMapping.get(s1); + if (tz != null) { + cal.setTimeZone(tz); + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + continue; + } + if (voidData.contains(s1)) { + if (s1.equalsIgnoreCase("pm")) cal.add(Calendar.AM_PM, Calendar.PM); + if (s1.equalsIgnoreCase("am")) cal.add(Calendar.AM_PM, Calendar.AM); + if (!st.hasMoreTokens()) return null; + s1 = st.nextToken(); + continue; + } + return s1; + } + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/DefaultConverter.java b/accessors-smart/src/main/java/net/minidev/asm/DefaultConverter.java index 587611d..e7bd7ec 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/DefaultConverter.java +++ b/accessors-smart/src/main/java/net/minidev/asm/DefaultConverter.java @@ -3,305 +3,275 @@ import net.minidev.asm.ex.ConvertException; /** - * Provides utility methods to convert objects to different primitive types and their wrapper classes. - * It supports conversion from {@link Number} instances and {@link String} representations of numbers - * to their corresponding primitive types or wrapper classes. Conversion from types that are not supported - * will result in a {@link ConvertException}. + * Provides utility methods to convert objects to different primitive types and their wrapper + * classes. It supports conversion from {@link Number} instances and {@link String} representations + * of numbers to their corresponding primitive types or wrapper classes. Conversion from types that + * are not supported will result in a {@link ConvertException}. */ public class DefaultConverter { - /** - * Default constructor - */ - public DefaultConverter() { - super(); - } - /** - * Converts the given object to an {@code int}. - * - * @param obj the object to convert - * @return the converted int value, or 0 if the object is {@code null} - * @throws ConvertException if the object cannot be converted to an int - */ - public static int convertToint(Object obj) { - if (obj == null) - return 0; - if (obj instanceof Number) - return ((Number) obj).intValue(); - if (obj instanceof String) - return Integer.parseInt((String) obj); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to int"); - } + /** Default constructor */ + public DefaultConverter() { + super(); + } - /** - * Converts the given object to an {@link Integer}. - * - * @param obj the object to convert - * @return the converted Integer, or {@code null} if the object is {@code null} - * @throws ConvertException if the object cannot be converted to an Integer - */ - public static Integer convertToInt(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Integer.class) - return (Integer) obj; - if (obj instanceof Number) - return Integer.valueOf(((Number) obj).intValue()); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to Integer"); - } + /** + * Converts the given object to an {@code int}. + * + * @param obj the object to convert + * @return the converted int value, or 0 if the object is {@code null} + * @throws ConvertException if the object cannot be converted to an int + */ + public static int convertToint(Object obj) { + if (obj == null) return 0; + if (obj instanceof Number) return ((Number) obj).intValue(); + if (obj instanceof String) return Integer.parseInt((String) obj); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to int"); + } - /** - * Converts the given object to a {@code short}. - * - * @param obj the object to convert - * @return the converted short value, or 0 if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a short - */ - public static short convertToshort(Object obj) { - if (obj == null) - return 0; - if (obj instanceof Number) - return ((Number) obj).shortValue(); - if (obj instanceof String) - return Short.parseShort((String) obj); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to short"); - } + /** + * Converts the given object to an {@link Integer}. + * + * @param obj the object to convert + * @return the converted Integer, or {@code null} if the object is {@code null} + * @throws ConvertException if the object cannot be converted to an Integer + */ + public static Integer convertToInt(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Integer.class) return (Integer) obj; + if (obj instanceof Number) return Integer.valueOf(((Number) obj).intValue()); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to Integer"); + } - /** - * Converts the given object to a {@code short}. - * - * @param obj the object to convert - * @return the converted short value, or 0 if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a short - */ - public static Short convertToShort(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Short.class) - return (Short) obj; - if (obj instanceof Number) - return Short.valueOf(((Number) obj).shortValue()); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to Short"); - } + /** + * Converts the given object to a {@code short}. + * + * @param obj the object to convert + * @return the converted short value, or 0 if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a short + */ + public static short convertToshort(Object obj) { + if (obj == null) return 0; + if (obj instanceof Number) return ((Number) obj).shortValue(); + if (obj instanceof String) return Short.parseShort((String) obj); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to short"); + } - /** - * Converts the given object to a {@code long}. - * - * @param obj the object to convert - * @return the converted long value, or 0 if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a long - */ - public static long convertTolong(Object obj) { - if (obj == null) - return 0; - if (obj instanceof Number) - return ((Number) obj).longValue(); - if (obj instanceof String) - return Long.parseLong((String) obj); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to long"); - } + /** + * Converts the given object to a {@code short}. + * + * @param obj the object to convert + * @return the converted short value, or 0 if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a short + */ + public static Short convertToShort(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Short.class) return (Short) obj; + if (obj instanceof Number) return Short.valueOf(((Number) obj).shortValue()); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to Short"); + } - /** - * Converts the given object to a {@link Long}. - * - * @param obj the object to convert - * @return the converted Long, or {@code null} if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a Long - */ - public static Long convertToLong(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Long.class) - return (Long) obj; - if (obj instanceof Number) - return Long.valueOf(((Number) obj).longValue()); - throw new ConvertException("Primitive: Can not convert value '" + obj+ "' As " + obj.getClass().getName() + " to Long"); - } + /** + * Converts the given object to a {@code long}. + * + * @param obj the object to convert + * @return the converted long value, or 0 if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a long + */ + public static long convertTolong(Object obj) { + if (obj == null) return 0; + if (obj instanceof Number) return ((Number) obj).longValue(); + if (obj instanceof String) return Long.parseLong((String) obj); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to long"); + } - /** - * Converts the given object to a {@code byte}. - * - * @param obj the object to convert - * @return the converted byte value, or 0 if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a byte - */ - public static byte convertTobyte(Object obj) { - if (obj == null) - return 0; - if (obj instanceof Number) - return ((Number) obj).byteValue(); - if (obj instanceof String) - return Byte.parseByte((String) obj); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to byte"); - } + /** + * Converts the given object to a {@link Long}. + * + * @param obj the object to convert + * @return the converted Long, or {@code null} if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a Long + */ + public static Long convertToLong(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Long.class) return (Long) obj; + if (obj instanceof Number) return Long.valueOf(((Number) obj).longValue()); + throw new ConvertException( + "Primitive: Can not convert value '" + + obj + + "' As " + + obj.getClass().getName() + + " to Long"); + } - /** - * Converts the given object to a {@link Byte}. - * - * @param obj the object to convert - * @return the converted Byte, or {@code null} if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a Byte - */ - public static Byte convertToByte(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Byte.class) - return (Byte) obj; - if (obj instanceof Number) - return Byte.valueOf(((Number) obj).byteValue()); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to Byte"); - } + /** + * Converts the given object to a {@code byte}. + * + * @param obj the object to convert + * @return the converted byte value, or 0 if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a byte + */ + public static byte convertTobyte(Object obj) { + if (obj == null) return 0; + if (obj instanceof Number) return ((Number) obj).byteValue(); + if (obj instanceof String) return Byte.parseByte((String) obj); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to byte"); + } - /** - * Converts the given object to a {@code float}. - * - * @param obj the object to convert - * @return the converted float value, or 0f if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a float - */ - public static float convertTofloat(Object obj) { - if (obj == null) - return 0f; - if (obj instanceof Number) - return ((Number) obj).floatValue(); - if (obj instanceof String) - return Float.parseFloat((String) obj); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to float"); - } + /** + * Converts the given object to a {@link Byte}. + * + * @param obj the object to convert + * @return the converted Byte, or {@code null} if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a Byte + */ + public static Byte convertToByte(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Byte.class) return (Byte) obj; + if (obj instanceof Number) return Byte.valueOf(((Number) obj).byteValue()); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to Byte"); + } - /** - * Converts the given object to a {@link Byte}. - * - * @param obj the object to convert - * @return the converted Byte, or {@code null} if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a Byte - */ - public static Float convertToFloat(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Float.class) - return (Float) obj; - if (obj instanceof Number) - return Float.valueOf(((Number) obj).floatValue()); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to Float"); - } + /** + * Converts the given object to a {@code float}. + * + * @param obj the object to convert + * @return the converted float value, or 0f if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a float + */ + public static float convertTofloat(Object obj) { + if (obj == null) return 0f; + if (obj instanceof Number) return ((Number) obj).floatValue(); + if (obj instanceof String) return Float.parseFloat((String) obj); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to float"); + } - /** - * Converts the given object to a {@code double}. - * - * @param obj the object to convert - * @return the converted double value, or 0.0 if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a double - */ - public static double convertTodouble(Object obj) { - if (obj == null) - return 0.0; - if (obj instanceof Number) - return ((Number) obj).doubleValue(); - if (obj instanceof String) - return Double.parseDouble((String) obj); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to float"); - } + /** + * Converts the given object to a {@link Byte}. + * + * @param obj the object to convert + * @return the converted Byte, or {@code null} if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a Byte + */ + public static Float convertToFloat(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Float.class) return (Float) obj; + if (obj instanceof Number) return Float.valueOf(((Number) obj).floatValue()); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to Float"); + } - /** - * Converts the given object to a {@link Double}. - * - * @param obj the object to convert - * @return the converted Double, or {@code null} if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a Double - */ - public static Double convertToDouble(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Double.class) - return (Double) obj; - if (obj instanceof Number) - return Double.valueOf(((Number) obj).doubleValue()); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to Float"); - } + /** + * Converts the given object to a {@code double}. + * + * @param obj the object to convert + * @return the converted double value, or 0.0 if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a double + */ + public static double convertTodouble(Object obj) { + if (obj == null) return 0.0; + if (obj instanceof Number) return ((Number) obj).doubleValue(); + if (obj instanceof String) return Double.parseDouble((String) obj); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to float"); + } - /** - * Converts the given object to a {@code char}. - * - * @param obj the object to convert - * @return the converted char value, or a space character if the object is {@code null} or the string is empty - * @throws ConvertException if the object cannot be converted to a char - */ - public static char convertTochar(Object obj) { - if (obj == null) - return ' '; - if (obj instanceof String) - if (((String) obj).length() > 0) - return ((String) obj).charAt(0); - else - return ' '; - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to char"); - } + /** + * Converts the given object to a {@link Double}. + * + * @param obj the object to convert + * @return the converted Double, or {@code null} if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a Double + */ + public static Double convertToDouble(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Double.class) return (Double) obj; + if (obj instanceof Number) return Double.valueOf(((Number) obj).doubleValue()); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to Float"); + } - /** - * Converts the given object to a {@link Character}. - * - * @param obj the object to convert - * @return the converted Character, or {@code null} if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a Character - */ - public static Character convertToChar(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Character.class) - return (Character) obj; - if (obj instanceof String) - if (((String) obj).length() > 0) - return ((String) obj).charAt(0); - else - return ' '; - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to Character"); - } + /** + * Converts the given object to a {@code char}. + * + * @param obj the object to convert + * @return the converted char value, or a space character if the object is {@code null} or the + * string is empty + * @throws ConvertException if the object cannot be converted to a char + */ + public static char convertTochar(Object obj) { + if (obj == null) return ' '; + if (obj instanceof String) + if (((String) obj).length() > 0) return ((String) obj).charAt(0); + else return ' '; + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to char"); + } - /** - * Converts the given object to a {@code boolean}. - * - * @param obj the object to convert - * @return the converted boolean value, false if the object is {@code null} or represents the numeric value 0 - * @throws ConvertException if the object cannot be converted to a boolean - */ - public static boolean convertTobool(Object obj) { - if (obj == null) - return false; - if (obj.getClass() == Boolean.class) - return ((Boolean) obj).booleanValue(); - if (obj instanceof String) - return Boolean.parseBoolean((String) obj); - if (obj instanceof Number) { - if (obj.toString().equals("0")) - return false; - else - return true; - } - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to boolean"); - } + /** + * Converts the given object to a {@link Character}. + * + * @param obj the object to convert + * @return the converted Character, or {@code null} if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a Character + */ + public static Character convertToChar(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Character.class) return (Character) obj; + if (obj instanceof String) + if (((String) obj).length() > 0) return ((String) obj).charAt(0); + else return ' '; + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to Character"); + } - /** - * Converts the given object to a {@link Boolean}. - * - * @param obj the object to convert - * @return the converted Boolean, or {@code null} if the object is {@code null} - * @throws ConvertException if the object cannot be converted to a Boolean - */ - public static Boolean convertToBool(Object obj) { - if (obj == null) - return null; - Class c = obj.getClass(); - if (c == Boolean.class) - return (Boolean) obj; - if (obj instanceof String) - return Boolean.parseBoolean((String) obj); - throw new ConvertException("Primitive: Can not convert " + obj.getClass().getName() + " to Boolean"); - } + /** + * Converts the given object to a {@code boolean}. + * + * @param obj the object to convert + * @return the converted boolean value, false if the object is {@code null} or represents the + * numeric value 0 + * @throws ConvertException if the object cannot be converted to a boolean + */ + public static boolean convertTobool(Object obj) { + if (obj == null) return false; + if (obj.getClass() == Boolean.class) return ((Boolean) obj).booleanValue(); + if (obj instanceof String) return Boolean.parseBoolean((String) obj); + if (obj instanceof Number) { + if (obj.toString().equals("0")) return false; + else return true; + } + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to boolean"); + } + + /** + * Converts the given object to a {@link Boolean}. + * + * @param obj the object to convert + * @return the converted Boolean, or {@code null} if the object is {@code null} + * @throws ConvertException if the object cannot be converted to a Boolean + */ + public static Boolean convertToBool(Object obj) { + if (obj == null) return null; + Class c = obj.getClass(); + if (c == Boolean.class) return (Boolean) obj; + if (obj instanceof String) return Boolean.parseBoolean((String) obj); + throw new ConvertException( + "Primitive: Can not convert " + obj.getClass().getName() + " to Boolean"); + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/DynamicClassLoader.java b/accessors-smart/src/main/java/net/minidev/asm/DynamicClassLoader.java index a1076e3..edf58bd 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/DynamicClassLoader.java +++ b/accessors-smart/src/main/java/net/minidev/asm/DynamicClassLoader.java @@ -18,71 +18,71 @@ import java.lang.reflect.Method; /** - * Simple extension from ClassLoader overriding the loadClass(String name, - * boolean resolve) method and allowing to register new classes - * + * Simple extension from ClassLoader overriding the loadClass(String name, boolean resolve) method + * and allowing to register new classes + * * @author uriel - * */ class DynamicClassLoader extends ClassLoader { - DynamicClassLoader(ClassLoader parent) { - super(parent); - } + DynamicClassLoader(ClassLoader parent) { + super(parent); + } + + private static final String BEAN_AC = BeansAccess.class.getName(); - private final static String BEAN_AC = BeansAccess.class.getName(); - /** - * Predefined define defineClass method signature (name, bytes, offset, - * length) - */ - private final static Class[] DEF_CLASS_SIG = new Class[] { String.class, byte[].class, int.class, int.class }; + /** Predefined define defineClass method signature (name, bytes, offset, length) */ + private static final Class[] DEF_CLASS_SIG = + new Class[] {String.class, byte[].class, int.class, int.class}; - /** - * - * @param parent used to choose the ClassLoader - * @param clsName C - * @param clsData - * @return - */ - public static Class directLoad(Class parent, String clsName, byte[] clsData) { - DynamicClassLoader loader = new DynamicClassLoader(parent.getClassLoader()); - @SuppressWarnings("unchecked") - Class clzz = (Class) loader.defineClass(clsName, clsData); - return clzz; - } + /** + * @param parent used to choose the ClassLoader + * @param clsName C + * @param clsData + * @return + */ + public static Class directLoad(Class parent, String clsName, byte[] clsData) { + DynamicClassLoader loader = new DynamicClassLoader(parent.getClassLoader()); + @SuppressWarnings("unchecked") + Class clzz = (Class) loader.defineClass(clsName, clsData); + return clzz; + } - public static T directInstance(Class parent, String clsName, byte[] clsData) throws InstantiationException, IllegalAccessException { - Class clzz = directLoad(parent, clsName, clsData); - return clzz.newInstance(); - } + public static T directInstance(Class parent, String clsName, byte[] clsData) + throws InstantiationException, IllegalAccessException { + Class clzz = directLoad(parent, clsName, clsData); + return clzz.newInstance(); + } - @Override - protected synchronized java.lang.Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - /* - * check class by fullname as String. - */ - if (name.equals(BEAN_AC)) - return BeansAccess.class; - /* - * Use default class loader - */ - return super.loadClass(name, resolve); - } + @Override + protected synchronized java.lang.Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + /* + * check class by fullname as String. + */ + if (name.equals(BEAN_AC)) return BeansAccess.class; + /* + * Use default class loader + */ + return super.loadClass(name, resolve); + } - /** - * Call defineClass into the parent classLoader using the - * method.setAccessible(boolean) hack - * - * @see ClassLoader#defineClass(String, byte[], int, int) - */ - Class defineClass(String name, byte[] bytes) throws ClassFormatError { - try { - // Attempt to load the access class in the same loader, which makes - // protected and default access members accessible. - Method method = ClassLoader.class.getDeclaredMethod("defineClass", DEF_CLASS_SIG); - method.setAccessible(true); - return (Class) method.invoke(getParent(), new Object[] { name, bytes, Integer.valueOf(0), Integer.valueOf(bytes.length) }); - } catch (Exception ignored) { - } - return defineClass(name, bytes, 0, bytes.length); - } + /** + * Call defineClass into the parent classLoader using the method.setAccessible(boolean) hack + * + * @see ClassLoader#defineClass(String, byte[], int, int) + */ + Class defineClass(String name, byte[] bytes) throws ClassFormatError { + try { + // Attempt to load the access class in the same loader, which makes + // protected and default access members accessible. + Method method = ClassLoader.class.getDeclaredMethod("defineClass", DEF_CLASS_SIG); + method.setAccessible(true); + return (Class) + method.invoke( + getParent(), + new Object[] {name, bytes, Integer.valueOf(0), Integer.valueOf(bytes.length)}); + } catch (Exception ignored) { + } + return defineClass(name, bytes, 0, bytes.length); + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/FieldFilter.java b/accessors-smart/src/main/java/net/minidev/asm/FieldFilter.java index fd1f2df..c7e5e28 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/FieldFilter.java +++ b/accessors-smart/src/main/java/net/minidev/asm/FieldFilter.java @@ -3,41 +3,38 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; -/** - * allow to control read/write access to field - * - */ +/** allow to control read/write access to field */ public interface FieldFilter { - /** - * NOT Implemented YET - * - * @param field the field - * @return boolean - */ - public boolean canUse(Field field); + /** + * NOT Implemented YET + * + * @param field the field + * @return boolean + */ + public boolean canUse(Field field); - /** - * Can the field be used - * - * @param field the field - * @param method the method - * @return boolean - */ - public boolean canUse(Field field, Method method); + /** + * Can the field be used + * + * @param field the field + * @param method the method + * @return boolean + */ + public boolean canUse(Field field, Method method); - /** - * NOT Implemented YET - * - * @param field the field - * @return boolean - */ - public boolean canRead(Field field); + /** + * NOT Implemented YET + * + * @param field the field + * @return boolean + */ + public boolean canRead(Field field); - /** - * NOT Implemented YET - * - * @param field the field - * @return boolean - */ - public boolean canWrite(Field field); + /** + * NOT Implemented YET + * + * @param field the field + * @return boolean + */ + public boolean canWrite(Field field); } diff --git a/accessors-smart/src/main/java/net/minidev/asm/ex/ConvertException.java b/accessors-smart/src/main/java/net/minidev/asm/ex/ConvertException.java index 6646aa1..22089c9 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/ex/ConvertException.java +++ b/accessors-smart/src/main/java/net/minidev/asm/ex/ConvertException.java @@ -1,29 +1,29 @@ package net.minidev.asm.ex; /** - * An exception that is thrown to indicate a problem occurred during a conversion process. - * This class extends {@link RuntimeException} and is used to signify errors encountered - * while converting between types, typically within a dynamic type conversion framework or library. + * An exception that is thrown to indicate a problem occurred during a conversion process. This + * class extends {@link RuntimeException} and is used to signify errors encountered while converting + * between types, typically within a dynamic type conversion framework or library. */ public class ConvertException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - /** - * Constructs a new {@code ConvertException} with {@code null} as its detail message. - * The cause is not initialized, and may subsequently be initialized by a call to {@link #initCause}. - */ - public ConvertException() { - super(); - } - - /** - * Constructs a new {@code ConvertException} with the specified detail message. - * The cause is not initialized, and may subsequently be initialized by a call to {@link #initCause}. - * - * @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()} method. - */ - public ConvertException(String message) { - super(message); - } + /** + * Constructs a new {@code ConvertException} with {@code null} as its detail message. The cause is + * not initialized, and may subsequently be initialized by a call to {@link #initCause}. + */ + public ConvertException() { + super(); + } + /** + * Constructs a new {@code ConvertException} with the specified detail message. The cause is not + * initialized, and may subsequently be initialized by a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for later retrieval by the + * {@link #getMessage()} method. + */ + public ConvertException(String message) { + super(message); + } } diff --git a/accessors-smart/src/main/java/net/minidev/asm/ex/NoSuchFieldException.java b/accessors-smart/src/main/java/net/minidev/asm/ex/NoSuchFieldException.java index 07c29df..4438725 100644 --- a/accessors-smart/src/main/java/net/minidev/asm/ex/NoSuchFieldException.java +++ b/accessors-smart/src/main/java/net/minidev/asm/ex/NoSuchFieldException.java @@ -2,26 +2,24 @@ /** * Same exception as java.lang.NoSuchFieldException but extends RuntimException - * - * @author uriel * + * @author uriel */ public class NoSuchFieldException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - /** - * default constructor - */ - public NoSuchFieldException() { - super(); - } + /** default constructor */ + public NoSuchFieldException() { + super(); + } - /** - * constuctor from message. - * @param message the detail message. The detail message is saved for - * later retrieval by the Throwable.getMessage() method. - */ - public NoSuchFieldException(String message) { - super(message); - } + /** + * constuctor from message. + * + * @param message the detail message. The detail message is saved for later retrieval by the + * Throwable.getMessage() method. + */ + public NoSuchFieldException(String message) { + super(message); + } } diff --git a/accessors-smart/src/test/java/com/mindev/pojos/AccessorTestPojo.java b/accessors-smart/src/test/java/com/mindev/pojos/AccessorTestPojo.java index 8903f3f..70d9c74 100644 --- a/accessors-smart/src/test/java/com/mindev/pojos/AccessorTestPojo.java +++ b/accessors-smart/src/test/java/com/mindev/pojos/AccessorTestPojo.java @@ -2,30 +2,29 @@ public class AccessorTestPojo { - // Field with only setter method - @SuppressWarnings("unused") - private int writeOnlyField; - - // Field with only getter method - private int readOnlyField; - - // Field with both getter and setter methods - private int readAndWriteableField; - - public void setWriteOnlyField(int writeOnlyField) { - this.writeOnlyField = writeOnlyField; - } - - public int getReadOnlyField() { - return readOnlyField; - } - - public int getReadAndWriteableField() { - return readAndWriteableField; - } - - public void setReadAndWriteableField(int readAndWriteableField) { - this.readAndWriteableField = readAndWriteableField; - } + // Field with only setter method + @SuppressWarnings("unused") + private int writeOnlyField; + // Field with only getter method + private int readOnlyField; + + // Field with both getter and setter methods + private int readAndWriteableField; + + public void setWriteOnlyField(int writeOnlyField) { + this.writeOnlyField = writeOnlyField; + } + + public int getReadOnlyField() { + return readOnlyField; + } + + public int getReadAndWriteableField() { + return readAndWriteableField; + } + + public void setReadAndWriteableField(int readAndWriteableField) { + this.readAndWriteableField = readAndWriteableField; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/ASMTest.java b/accessors-smart/src/test/java/net/minidev/asm/ASMTest.java index 9198be3..af94f8b 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/ASMTest.java +++ b/accessors-smart/src/test/java/net/minidev/asm/ASMTest.java @@ -3,129 +3,127 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.HashMap; - -import org.junit.jupiter.api.Test; - import net.minidev.asm.bean.BTest; +import org.junit.jupiter.api.Test; public class ASMTest { - @Test - public void testGet() throws Exception { - // long T1; - - BeansAccess acBT = BeansAccess.get(BTest.class); - // BeansAccess acHand = new BTestBeansAccessB(); - - HashMap m = new HashMap(); - m.put("A", "ab"); - m.put("B", "Bc"); - m.put("C", "cD"); - m.put("D", "de"); - m.put("E", "ef"); - - // String clsPath = FastMap1Builder.getName(m.size()); - // String clsName = clsPath.replace("/", "."); - - // byte[] data; - - // data = FastMap1Builder.dump(m.size()); - // data = FastMap2Builder.dump(m); - // data = FastMapTestDump.dump(clsPath); - - // DynamicClassLoader loader = new - // DynamicClassLoader(BTest.class.getClassLoader()); - // byte[] data = BTestBeansAccessDump.dump(); - // Class cls = (Class) loader.defineClass(clsName, - // data); - // Constructor c = (Constructor) - // cls.getConstructors()[0]; - // FastMap f = c.newInstance(m); - // f = new FastMapTest_2(m); - // f = new FastMapTest_3(); - // f = new FastMapTest_2(m); - // f = new FastMapTest_3(); - // 4 entré - // map => 1.279 - // fastMap => 3.323 - // FastMapTest_1 3.323 - // FastMapTest_2 3.323 - // FastMapTest_3 0.015 - - // 3 entry - // map => 0.983 - // fastmap => 1.014 - // 2 entry - // map => 0,920 - // fastMap => 0,608 - - // 7 entry - // f 2.667 - // m 0,640 - - // 6 entree - // f 2.215 - // m 0,608 - - // 4 entree - // f 0.032 - // m 0,593 - - // 5 entree - // f - // m 0.609 - // V2 2.402 - // V3 2.247 - // for (int i = 0; i < 20000; i++) { - // f.get("A"); - // f.get("B"); - // f.get("C"); - // f.get("D"); - // f.get("E"); - // f.get("F"); - // f.get("G"); - // f.get("H"); - // f.get("I"); - // } - // System.gc(); - // long T = System.nanoTime(); - // for (int i = 0; i < 20000000; i++) { - // m.get("A"); - // m.get("B"); - // m.get("C"); - // m.get("D"); - // m.get("E"); - // m.get("F"); - // m.get("G"); - // m.get("H"); - // m.get("I"); - // } - // T = System.nanoTime() - T; - // 10 774 968 - // 596 295 451 - // 2 321 087 341 - - BeansAccess ac; - ac = acBT; - // ac = acHand; - // ac = acASMHand; - subtext(ac); - // T1 = System.currentTimeMillis(); - // for (int i = 0; i < 2000000; i++) - // subtext(ac); - // T1 = System.currentTimeMillis() - T1; - } - - @Test - private void subtext(BeansAccess acc) { - BTest t = new BTest(); - acc.set(t, "pubBoolValue", true); - acc.set(t, "pubIntValue", 13); - acc.set(t, "pubStrValue", "Test"); - acc.set(t, "privIntValue", 16); - acc.set(t, "privStrValue", "test Priv"); - assertEquals(Integer.valueOf(13), acc.get(t, "pubIntValue")); - acc.set(t, "pubIntValue", 14); - assertEquals(Integer.valueOf(14), acc.get(t, "pubIntValue")); - } -} \ No newline at end of file + @Test + public void testGet() throws Exception { + // long T1; + + BeansAccess acBT = BeansAccess.get(BTest.class); + // BeansAccess acHand = new BTestBeansAccessB(); + + HashMap m = new HashMap(); + m.put("A", "ab"); + m.put("B", "Bc"); + m.put("C", "cD"); + m.put("D", "de"); + m.put("E", "ef"); + + // String clsPath = FastMap1Builder.getName(m.size()); + // String clsName = clsPath.replace("/", "."); + + // byte[] data; + + // data = FastMap1Builder.dump(m.size()); + // data = FastMap2Builder.dump(m); + // data = FastMapTestDump.dump(clsPath); + + // DynamicClassLoader loader = new + // DynamicClassLoader(BTest.class.getClassLoader()); + // byte[] data = BTestBeansAccessDump.dump(); + // Class cls = (Class) loader.defineClass(clsName, + // data); + // Constructor c = (Constructor) + // cls.getConstructors()[0]; + // FastMap f = c.newInstance(m); + // f = new FastMapTest_2(m); + // f = new FastMapTest_3(); + // f = new FastMapTest_2(m); + // f = new FastMapTest_3(); + // 4 entré + // map => 1.279 + // fastMap => 3.323 + // FastMapTest_1 3.323 + // FastMapTest_2 3.323 + // FastMapTest_3 0.015 + + // 3 entry + // map => 0.983 + // fastmap => 1.014 + // 2 entry + // map => 0,920 + // fastMap => 0,608 + + // 7 entry + // f 2.667 + // m 0,640 + + // 6 entree + // f 2.215 + // m 0,608 + + // 4 entree + // f 0.032 + // m 0,593 + + // 5 entree + // f + // m 0.609 + // V2 2.402 + // V3 2.247 + // for (int i = 0; i < 20000; i++) { + // f.get("A"); + // f.get("B"); + // f.get("C"); + // f.get("D"); + // f.get("E"); + // f.get("F"); + // f.get("G"); + // f.get("H"); + // f.get("I"); + // } + // System.gc(); + // long T = System.nanoTime(); + // for (int i = 0; i < 20000000; i++) { + // m.get("A"); + // m.get("B"); + // m.get("C"); + // m.get("D"); + // m.get("E"); + // m.get("F"); + // m.get("G"); + // m.get("H"); + // m.get("I"); + // } + // T = System.nanoTime() - T; + // 10 774 968 + // 596 295 451 + // 2 321 087 341 + + BeansAccess ac; + ac = acBT; + // ac = acHand; + // ac = acASMHand; + subtext(ac); + // T1 = System.currentTimeMillis(); + // for (int i = 0; i < 2000000; i++) + // subtext(ac); + // T1 = System.currentTimeMillis() - T1; + } + + @Test + private void subtext(BeansAccess acc) { + BTest t = new BTest(); + acc.set(t, "pubBoolValue", true); + acc.set(t, "pubIntValue", 13); + acc.set(t, "pubStrValue", "Test"); + acc.set(t, "privIntValue", 16); + acc.set(t, "privStrValue", "test Priv"); + assertEquals(Integer.valueOf(13), acc.get(t, "pubIntValue")); + acc.set(t, "pubIntValue", 14); + assertEquals(Integer.valueOf(14), acc.get(t, "pubIntValue")); + } +} diff --git a/accessors-smart/src/test/java/net/minidev/asm/AccessorTest.java b/accessors-smart/src/test/java/net/minidev/asm/AccessorTest.java index 6d0c9d0..8272597 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/AccessorTest.java +++ b/accessors-smart/src/test/java/net/minidev/asm/AccessorTest.java @@ -3,104 +3,99 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.mindev.pojos.AccessorTestPojo; import java.lang.reflect.Field; import java.lang.reflect.Method; - import org.junit.jupiter.api.Test; -import com.mindev.pojos.AccessorTestPojo; - public class AccessorTest { - private static class AcceptAllFilter implements FieldFilter { - - @Override - public boolean canUse(Field field) { - return true; - } - - @Override - public boolean canUse(Field field, Method method) { - return true; - } - - @Override - public boolean canRead(Field field) { - return true; - } - - @Override - public boolean canWrite(Field field) { - return true; - } + private static class AcceptAllFilter implements FieldFilter { - } + @Override + public boolean canUse(Field field) { + return true; + } - private static class AcceptNoneFilter implements FieldFilter { + @Override + public boolean canUse(Field field, Method method) { + return true; + } - @Override - public boolean canUse(Field field) { - return false; - } + @Override + public boolean canRead(Field field) { + return true; + } - @Override - public boolean canUse(Field field, Method method) { - return false; - } + @Override + public boolean canWrite(Field field) { + return true; + } + } - @Override - public boolean canRead(Field field) { - return false; - } + private static class AcceptNoneFilter implements FieldFilter { - @Override - public boolean canWrite(Field field) { - return false; - } + @Override + public boolean canUse(Field field) { + return false; + } - } + @Override + public boolean canUse(Field field, Method method) { + return false; + } - @Test - public void testWriteOnlyField() throws NoSuchFieldException, SecurityException { + @Override + public boolean canRead(Field field) { + return false; + } - Field writeOnlyField = AccessorTestPojo.class.getDeclaredField("writeOnlyField"); - Accessor accessor = new Accessor(AccessorTestPojo.class, writeOnlyField, new AcceptAllFilter()); + @Override + public boolean canWrite(Field field) { + return false; + } + } - assertTrue(accessor.isWritable()); - assertFalse(accessor.isReadable()); + @Test + public void testWriteOnlyField() throws NoSuchFieldException, SecurityException { - accessor = new Accessor(AccessorTestPojo.class, writeOnlyField, new AcceptNoneFilter()); - assertFalse(accessor.isWritable()); - assertFalse(accessor.isReadable()); + Field writeOnlyField = AccessorTestPojo.class.getDeclaredField("writeOnlyField"); + Accessor accessor = new Accessor(AccessorTestPojo.class, writeOnlyField, new AcceptAllFilter()); - } + assertTrue(accessor.isWritable()); + assertFalse(accessor.isReadable()); - @Test - public void testReadOnlyField() throws NoSuchFieldException, SecurityException { + accessor = new Accessor(AccessorTestPojo.class, writeOnlyField, new AcceptNoneFilter()); + assertFalse(accessor.isWritable()); + assertFalse(accessor.isReadable()); + } - Field readOnlyField = AccessorTestPojo.class.getDeclaredField("readOnlyField"); - Accessor accessor = new Accessor(AccessorTestPojo.class, readOnlyField, new AcceptAllFilter()); + @Test + public void testReadOnlyField() throws NoSuchFieldException, SecurityException { - assertFalse(accessor.isWritable()); - assertTrue(accessor.isReadable()); + Field readOnlyField = AccessorTestPojo.class.getDeclaredField("readOnlyField"); + Accessor accessor = new Accessor(AccessorTestPojo.class, readOnlyField, new AcceptAllFilter()); - accessor = new Accessor(AccessorTestPojo.class, readOnlyField, new AcceptNoneFilter()); - assertFalse(accessor.isWritable()); - assertFalse(accessor.isReadable()); - } + assertFalse(accessor.isWritable()); + assertTrue(accessor.isReadable()); - @Test - public void testReadAndWriteableField() throws NoSuchFieldException, SecurityException { + accessor = new Accessor(AccessorTestPojo.class, readOnlyField, new AcceptNoneFilter()); + assertFalse(accessor.isWritable()); + assertFalse(accessor.isReadable()); + } - Field readAndWriteableField = AccessorTestPojo.class.getDeclaredField("readAndWriteableField"); - Accessor accessor = new Accessor(AccessorTestPojo.class, readAndWriteableField, new AcceptAllFilter()); + @Test + public void testReadAndWriteableField() throws NoSuchFieldException, SecurityException { - assertTrue(accessor.isWritable()); - assertTrue(accessor.isReadable()); + Field readAndWriteableField = AccessorTestPojo.class.getDeclaredField("readAndWriteableField"); + Accessor accessor = + new Accessor(AccessorTestPojo.class, readAndWriteableField, new AcceptAllFilter()); - accessor = new Accessor(AccessorTestPojo.class, readAndWriteableField, new AcceptNoneFilter()); - assertFalse(accessor.isWritable()); - assertFalse(accessor.isReadable()); - } + assertTrue(accessor.isWritable()); + assertTrue(accessor.isReadable()); + accessor = new Accessor(AccessorTestPojo.class, readAndWriteableField, new AcceptNoneFilter()); + assertFalse(accessor.isWritable()); + assertFalse(accessor.isReadable()); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/BTestBeansAccessB.java b/accessors-smart/src/test/java/net/minidev/asm/BTestBeansAccessB.java index 544a7c5..b567c42 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/BTestBeansAccessB.java +++ b/accessors-smart/src/test/java/net/minidev/asm/BTestBeansAccessB.java @@ -6,180 +6,167 @@ @SuppressWarnings("rawtypes") public class BTestBeansAccessB extends BeansAccess { - public BTestBeansAccessB() { - Accessor[] accs = ASMUtil.getAccessors(BTest.class, null); - super.setAccessor(accs); - } + public BTestBeansAccessB() { + Accessor[] accs = ASMUtil.getAccessors(BTest.class, null); + super.setAccessor(accs); + } - /** - * set field value by fieldname - */ - @Override - public void set(Object object, String methodName, Object value) { - if ("privIntValue".equals(methodName)) { - ((BTest) object).setPrivIntValue(DefaultConverter.convertToint(value)); - return; - } - if ("privStrValue".equals(methodName)) { - if (value != null) - value = value.toString(); - ((BTest) object).setPrivStrValue((String) value); - return; - } + /** set field value by fieldname */ + @Override + public void set(Object object, String methodName, Object value) { + if ("privIntValue".equals(methodName)) { + ((BTest) object).setPrivIntValue(DefaultConverter.convertToint(value)); + return; + } + if ("privStrValue".equals(methodName)) { + if (value != null) value = value.toString(); + ((BTest) object).setPrivStrValue((String) value); + return; + } - if ("pubStrValue".equals(methodName)) { - if (value != null) - value = value.toString(); - ((BTest) object).pubStrValue = (String) value; - return; - } - if ("pubIntValue".equals(methodName)) { - ((BTest) object).pubIntValue = DefaultConverter.convertToint(value); - return; - } - if ("pubBoolValue".equals(methodName)) { - ((BTest) object).pubBoolValue = DefaultConverter.convertTobool(value); - return; - } - if ("pubIntegerValue".equals(methodName)) { - ((BTest) object).pubIntegerValue = DefaultConverter.convertToInt(value); - return; - } - if ("pubTEnum".equals(methodName)) { - ((BTest) object).pubTEnum = TEnum.valueOf((String) value); - return; - } - } + if ("pubStrValue".equals(methodName)) { + if (value != null) value = value.toString(); + ((BTest) object).pubStrValue = (String) value; + return; + } + if ("pubIntValue".equals(methodName)) { + ((BTest) object).pubIntValue = DefaultConverter.convertToint(value); + return; + } + if ("pubBoolValue".equals(methodName)) { + ((BTest) object).pubBoolValue = DefaultConverter.convertTobool(value); + return; + } + if ("pubIntegerValue".equals(methodName)) { + ((BTest) object).pubIntegerValue = DefaultConverter.convertToInt(value); + return; + } + if ("pubTEnum".equals(methodName)) { + ((BTest) object).pubTEnum = TEnum.valueOf((String) value); + return; + } + } - /** - * get field value by fieldname - */ - @Override - public Object get(Object object, String methodName) { - if ("privIntValue".equals(methodName)) - return ((BTest) object).getPrivIntValue(); - if ("privStrValue".equals(methodName)) - return ((BTest) object).getPrivStrValue(); - if ("pubStrValue".equals(methodName)) - return ((BTest) object).pubStrValue; - if ("pubIntValue".equals(methodName)) - return ((BTest) object).pubIntValue; - if ("privStrValue".equals(methodName)) - return ((BTest) object).pubBoolValue; - if ("pubIntegerValue".equals(methodName)) - return ((BTest) object).pubIntegerValue; - if ("pubTEnum".equals(methodName)) - return ((BTest) object).pubTEnum; - return null; - } + /** get field value by fieldname */ + @Override + public Object get(Object object, String methodName) { + if ("privIntValue".equals(methodName)) return ((BTest) object).getPrivIntValue(); + if ("privStrValue".equals(methodName)) return ((BTest) object).getPrivStrValue(); + if ("pubStrValue".equals(methodName)) return ((BTest) object).pubStrValue; + if ("pubIntValue".equals(methodName)) return ((BTest) object).pubIntValue; + if ("privStrValue".equals(methodName)) return ((BTest) object).pubBoolValue; + if ("pubIntegerValue".equals(methodName)) return ((BTest) object).pubIntegerValue; + if ("pubTEnum".equals(methodName)) return ((BTest) object).pubTEnum; + return null; + } - @Override - public void set(Object object, int methodIndex, Object value) { - switch (methodIndex) { - case 0: // privIntValue; - ((BTest) object).setPrivIntValue(((Number) value).intValue()); - break; - case 1: // privStrValue; - ((BTest) object).setPrivStrValue((String) value); - break; - case 2: // pubStrValue; - ((BTest) object).pubStrValue = (String) value; - break; - case 3: // pubIntValue; - ((BTest) object).pubIntValue = ((Number) value).intValue(); - break; - case 4: // pubBoolValue; - ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); - break; - case 5: - ((BTest) object).pubIntegerValue = DefaultConverter.convertToInt(value); - break; - case 6: - ((BTest) object).pubTEnum = TEnum.valueOf((String) value); - break; - default: - break; - } - } + @Override + public void set(Object object, int methodIndex, Object value) { + switch (methodIndex) { + case 0: // privIntValue; + ((BTest) object).setPrivIntValue(((Number) value).intValue()); + break; + case 1: // privStrValue; + ((BTest) object).setPrivStrValue((String) value); + break; + case 2: // pubStrValue; + ((BTest) object).pubStrValue = (String) value; + break; + case 3: // pubIntValue; + ((BTest) object).pubIntValue = ((Number) value).intValue(); + break; + case 4: // pubBoolValue; + ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); + break; + case 5: + ((BTest) object).pubIntegerValue = DefaultConverter.convertToInt(value); + break; + case 6: + ((BTest) object).pubTEnum = TEnum.valueOf((String) value); + break; + default: + break; + } + } - public void setInt(Object object, int methodIndex, Object value) { - if (methodIndex == 0) { - ((BTest) object).setPrivIntValue(((Number) value).intValue()); - return; - } - if (methodIndex == 1) { - ((BTest) object).setPrivStrValue((String) value); - return; - } - if (methodIndex == 2) { - ((BTest) object).pubStrValue = (String) value; - return; - } - if (methodIndex == 3) { - ((BTest) object).pubIntValue = ((Number) value).intValue(); - return; - } - if (methodIndex == 4) { - ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); - return; - } - if (methodIndex == 5) { - ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); - return; - } - if (methodIndex == 0) { - ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); - return; - } - if (methodIndex == 7) { - ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); - return; - } - if (methodIndex == 8) { - ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); - return; - } - } + public void setInt(Object object, int methodIndex, Object value) { + if (methodIndex == 0) { + ((BTest) object).setPrivIntValue(((Number) value).intValue()); + return; + } + if (methodIndex == 1) { + ((BTest) object).setPrivStrValue((String) value); + return; + } + if (methodIndex == 2) { + ((BTest) object).pubStrValue = (String) value; + return; + } + if (methodIndex == 3) { + ((BTest) object).pubIntValue = ((Number) value).intValue(); + return; + } + if (methodIndex == 4) { + ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); + return; + } + if (methodIndex == 5) { + ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); + return; + } + if (methodIndex == 0) { + ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); + return; + } + if (methodIndex == 7) { + ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); + return; + } + if (methodIndex == 8) { + ((BTest) object).pubBoolValue = ((Boolean) value).booleanValue(); + return; + } + } - @Override - public Object get(Object object, int methodIndex) { - switch (methodIndex) { - case 0: // privIntValue; - return ((BTest) object).getPrivIntValue(); - case 1: // privStrValue; - return ((BTest) object).getPrivStrValue(); - case 2: // pubStrValue; - return ((BTest) object).pubStrValue; - case 3: // pubIntValue; - return ((BTest) object).pubIntValue; - case 4: // privStrValue; - return ((BTest) object).pubBoolValue; - case 5: // privStrValue; - return ((BTest) object).pubIntegerValue; - case 6: // privStrValue; - return ((BTest) object).pubTEnum; - default: - break; - } - return null; - } + @Override + public Object get(Object object, int methodIndex) { + switch (methodIndex) { + case 0: // privIntValue; + return ((BTest) object).getPrivIntValue(); + case 1: // privStrValue; + return ((BTest) object).getPrivStrValue(); + case 2: // pubStrValue; + return ((BTest) object).pubStrValue; + case 3: // pubIntValue; + return ((BTest) object).pubIntValue; + case 4: // privStrValue; + return ((BTest) object).pubBoolValue; + case 5: // privStrValue; + return ((BTest) object).pubIntegerValue; + case 6: // privStrValue; + return ((BTest) object).pubTEnum; + default: + break; + } + return null; + } - // public Object getInt(Object object, int methodIndex) { - // if (methodIndex == 0) - // return ((BTest) object).getPrivIntValue(); - // if (methodIndex == 1) - // return ((BTest) object).getPrivStrValue(); - // if (methodIndex == 2) - // return ((BTest) object).pubStrValue; - // if (methodIndex == 3) - // return ((BTest) object).pubIntValue; - // if (methodIndex == 4) - // return ((BTest) object).pubBoolValue; - // return null; - // } + // public Object getInt(Object object, int methodIndex) { + // if (methodIndex == 0) + // return ((BTest) object).getPrivIntValue(); + // if (methodIndex == 1) + // return ((BTest) object).getPrivStrValue(); + // if (methodIndex == 2) + // return ((BTest) object).pubStrValue; + // if (methodIndex == 3) + // return ((BTest) object).pubIntValue; + // if (methodIndex == 4) + // return ((BTest) object).pubBoolValue; + // return null; + // } - @Override - public Object newInstance() { - return new BTest(); - } + @Override + public Object newInstance() { + return new BTest(); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/TestDateConvert.java b/accessors-smart/src/test/java/net/minidev/asm/TestDateConvert.java index 276d6e8..20b7da3 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/TestDateConvert.java +++ b/accessors-smart/src/test/java/net/minidev/asm/TestDateConvert.java @@ -9,167 +9,163 @@ import java.util.Date; import java.util.Locale; import java.util.TimeZone; - import org.junit.jupiter.api.Test; public class TestDateConvert { - // we do not test the century - static TimeZone MY_TZ = TimeZone.getTimeZone("PST"); - - SimpleDateFormat sdfFull = new SimpleDateFormat("dd/MM/yy HH:mm:ss"); - SimpleDateFormat sdfLT = new SimpleDateFormat("dd/MM/yy HH:mm"); - - /** - * some old java version date API works differently an cause error in tests - * @return - */ - static int getJavaVersion() { - String javaVersion = System.getProperty("java.version"); - // Extracting major version from java version string - int majorVersion = Integer.parseInt(javaVersion.split("\\.")[1]); - return majorVersion; - } - - - @Test - public void testDateFR() throws Exception { - String expectedDateText = "23/01/12 13:42:12"; - ArrayList tests = new ArrayList(); - tests.add("23 janvier 2012 13:42:12"); - tests.add("lundi 23 janvier 2012 13:42:12"); - tests.add("2012-01-23 13:42:12"); - // need to use the same time Zone - // tests.add("Thu Jan 23 13:42:12 PST 2012"); - // - // tests.add("Thu Jan 23 13:42:12 CET 2012"); - ConvertDate.convertToDate(null); - for (String testDate : tests) { - String jobName = "Parsing FR Date:" + testDate; - Date parsed = null; - try { - parsed = ConvertDate.convertToDate(testDate); - } catch (Exception e) { - throw new Exception(jobName, e); - } - assertEquals(expectedDateText, sdfFull.format(parsed), jobName); - } - } - - public TestDateConvert() { - super(); - ConvertDate.defaultTimeZone = MY_TZ; - if (MY_TZ != null) { - sdfFull.setTimeZone(MY_TZ); - sdfLT.setTimeZone(MY_TZ); - } - } - - @Test - public void testAdvanceTimeStamp() throws Exception { - String testDate = "2014-08-27T12:53:10+02:00"; - ConvertDate.convertToDate(testDate); - } - - @Test - public void testDateUS() throws Exception { - testDateLocalized(Locale.US); - } - - @Test - public void testDateFRANCE() throws Exception { - testDateLocalized(Locale.FRANCE); - } - - @Test - public void testDateCANADA() throws Exception { - testDateLocalized(Locale.CANADA); - } - - @Test - public void testDateGERMANY() throws Exception { - testDateLocalized(Locale.GERMANY); - } - - @Test - public void testDateITALY() throws Exception { - testDateLocalized(Locale.ITALY); - } - - @Test - public void testDateCANADA_FRENCH() throws Exception { - testDateLocalized(Locale.CANADA_FRENCH); - } - - @Test - public void testDateJAPAN() throws Exception { - if (getJavaVersion() == 8) { - assertTrue(true, "Ignoring Japan Date test for Java 8"); - } else { - testDateLocalized(Locale.JAPAN); - } - } - - // public void testDateCHINA() throws Exception { - // testDateLocalized(Locale.CHINA); - // } - - // public void testDateCHINESE() throws Exception { - // testDateLocalized(Locale.CHINESE); - // } - - // MISSING CHINA / CHINESE - - public void testDateLocalized(Locale locale) throws Exception { - // PM test - Date pm = sdfFull.parse("23/01/2012 13:42:59"); - fullTestDate(pm, locale); - // AM test - Date am = sdfFull.parse("23/01/2012 01:42:59"); - fullTestDate(am, locale); - } - - /** - * Parse all JDK DateTimeFormat - */ - public void fullTestDate(Date expectedDate, Locale locale) throws Exception { - fullTestDate(expectedDate, locale, "SHORT", DateFormat.SHORT); - fullTestDate(expectedDate, locale, "MEDIUM", DateFormat.MEDIUM); - fullTestDate(expectedDate, locale, "LONG", DateFormat.LONG); - fullTestDate(expectedDate, locale, "FULL", DateFormat.FULL); - } - - public void fullTestDate(Date expectedDate, Locale locale, String sizeName, int sizeId) throws Exception { - DateFormat FormatEN = DateFormat.getDateTimeInstance(sizeId, sizeId, locale); - if (MY_TZ != null) { - FormatEN.setTimeZone(MY_TZ); - } - String testDate = FormatEN.format(expectedDate); - Date parse = null; - String jobName = "Test date format Local:" + locale + " size:" + sizeName + " String:\"" + testDate + "\""; - try { - // can not parse US style Date in short mode (due to reversed day/month). - if (sizeId == DateFormat.SHORT) { - if (locale.equals(Locale.US)) - return; - if (locale.equals(Locale.CANADA_FRENCH)) - return; - } - parse = ConvertDate.convertToDate(testDate); - } catch (Exception e) { - throw new Exception(jobName, e); - } - // System.err.println("TEST: " + testDate + " readed as: " + resultStr); - // is source format contains second - if (testDate.contains("59")) { - String resultStr = sdfFull.format(parse); - String expectedDateText = sdfFull.format(expectedDate); - assertEquals(expectedDateText, resultStr, jobName); - } else { - String resultStr = sdfLT.format(parse); - String expectedDateText = sdfLT.format(expectedDate); - assertEquals(expectedDateText, resultStr, jobName); - } - // System.err.printf("no sec for Format %-6s %-40s -> %10s\n", sizeName, testDate, resultStr); - } - + // we do not test the century + static TimeZone MY_TZ = TimeZone.getTimeZone("PST"); + + SimpleDateFormat sdfFull = new SimpleDateFormat("dd/MM/yy HH:mm:ss"); + SimpleDateFormat sdfLT = new SimpleDateFormat("dd/MM/yy HH:mm"); + + /** + * some old java version date API works differently an cause error in tests + * + * @return + */ + static int getJavaVersion() { + String javaVersion = System.getProperty("java.version"); + // Extracting major version from java version string + int majorVersion = Integer.parseInt(javaVersion.split("\\.")[1]); + return majorVersion; + } + + @Test + public void testDateFR() throws Exception { + String expectedDateText = "23/01/12 13:42:12"; + ArrayList tests = new ArrayList(); + tests.add("23 janvier 2012 13:42:12"); + tests.add("lundi 23 janvier 2012 13:42:12"); + tests.add("2012-01-23 13:42:12"); + // need to use the same time Zone + // tests.add("Thu Jan 23 13:42:12 PST 2012"); + // + // tests.add("Thu Jan 23 13:42:12 CET 2012"); + ConvertDate.convertToDate(null); + for (String testDate : tests) { + String jobName = "Parsing FR Date:" + testDate; + Date parsed = null; + try { + parsed = ConvertDate.convertToDate(testDate); + } catch (Exception e) { + throw new Exception(jobName, e); + } + assertEquals(expectedDateText, sdfFull.format(parsed), jobName); + } + } + + public TestDateConvert() { + super(); + ConvertDate.defaultTimeZone = MY_TZ; + if (MY_TZ != null) { + sdfFull.setTimeZone(MY_TZ); + sdfLT.setTimeZone(MY_TZ); + } + } + + @Test + public void testAdvanceTimeStamp() throws Exception { + String testDate = "2014-08-27T12:53:10+02:00"; + ConvertDate.convertToDate(testDate); + } + + @Test + public void testDateUS() throws Exception { + testDateLocalized(Locale.US); + } + + @Test + public void testDateFRANCE() throws Exception { + testDateLocalized(Locale.FRANCE); + } + + @Test + public void testDateCANADA() throws Exception { + testDateLocalized(Locale.CANADA); + } + + @Test + public void testDateGERMANY() throws Exception { + testDateLocalized(Locale.GERMANY); + } + + @Test + public void testDateITALY() throws Exception { + testDateLocalized(Locale.ITALY); + } + + @Test + public void testDateCANADA_FRENCH() throws Exception { + testDateLocalized(Locale.CANADA_FRENCH); + } + + @Test + public void testDateJAPAN() throws Exception { + if (getJavaVersion() == 8) { + assertTrue(true, "Ignoring Japan Date test for Java 8"); + } else { + testDateLocalized(Locale.JAPAN); + } + } + + // public void testDateCHINA() throws Exception { + // testDateLocalized(Locale.CHINA); + // } + + // public void testDateCHINESE() throws Exception { + // testDateLocalized(Locale.CHINESE); + // } + + // MISSING CHINA / CHINESE + + public void testDateLocalized(Locale locale) throws Exception { + // PM test + Date pm = sdfFull.parse("23/01/2012 13:42:59"); + fullTestDate(pm, locale); + // AM test + Date am = sdfFull.parse("23/01/2012 01:42:59"); + fullTestDate(am, locale); + } + + /** Parse all JDK DateTimeFormat */ + public void fullTestDate(Date expectedDate, Locale locale) throws Exception { + fullTestDate(expectedDate, locale, "SHORT", DateFormat.SHORT); + fullTestDate(expectedDate, locale, "MEDIUM", DateFormat.MEDIUM); + fullTestDate(expectedDate, locale, "LONG", DateFormat.LONG); + fullTestDate(expectedDate, locale, "FULL", DateFormat.FULL); + } + + public void fullTestDate(Date expectedDate, Locale locale, String sizeName, int sizeId) + throws Exception { + DateFormat FormatEN = DateFormat.getDateTimeInstance(sizeId, sizeId, locale); + if (MY_TZ != null) { + FormatEN.setTimeZone(MY_TZ); + } + String testDate = FormatEN.format(expectedDate); + Date parse = null; + String jobName = + "Test date format Local:" + locale + " size:" + sizeName + " String:\"" + testDate + "\""; + try { + // can not parse US style Date in short mode (due to reversed day/month). + if (sizeId == DateFormat.SHORT) { + if (locale.equals(Locale.US)) return; + if (locale.equals(Locale.CANADA_FRENCH)) return; + } + parse = ConvertDate.convertToDate(testDate); + } catch (Exception e) { + throw new Exception(jobName, e); + } + // System.err.println("TEST: " + testDate + " readed as: " + resultStr); + // is source format contains second + if (testDate.contains("59")) { + String resultStr = sdfFull.format(parse); + String expectedDateText = sdfFull.format(expectedDate); + assertEquals(expectedDateText, resultStr, jobName); + } else { + String resultStr = sdfLT.format(parse); + String expectedDateText = sdfLT.format(expectedDate); + assertEquals(expectedDateText, resultStr, jobName); + } + // System.err.printf("no sec for Format %-6s %-40s -> %10s\n", sizeName, testDate, resultStr); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/TestDateConvertCustom.java b/accessors-smart/src/test/java/net/minidev/asm/TestDateConvertCustom.java index d8d4aa4..43e9374 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/TestDateConvertCustom.java +++ b/accessors-smart/src/test/java/net/minidev/asm/TestDateConvertCustom.java @@ -1,17 +1,19 @@ package net.minidev.asm; import static org.junit.jupiter.api.Assertions.assertTrue; + import org.junit.jupiter.api.Test; public class TestDateConvertCustom { - /** - * some JAVA version use aternative space. - * @throws Exception - */ - @Test - public void testCANADACustom() throws Exception { - String testDate = "Jan 23, 2012, 1:42:59 PM"; - ConvertDate.convertToDate(testDate); - assertTrue(true, "parse " + testDate + " do not crash"); - } + /** + * some JAVA version use aternative space. + * + * @throws Exception + */ + @Test + public void testCANADACustom() throws Exception { + String testDate = "Jan 23, 2012, 1:42:59 PM"; + ConvertDate.convertToDate(testDate); + assertTrue(true, "parse " + testDate + " do not crash"); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/TestNewInstance.java b/accessors-smart/src/test/java/net/minidev/asm/TestNewInstance.java index f39ee0e..53f2f1b 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/TestNewInstance.java +++ b/accessors-smart/src/test/java/net/minidev/asm/TestNewInstance.java @@ -1,14 +1,13 @@ package net.minidev.asm; import java.util.TreeMap; - import org.junit.jupiter.api.Test; public class TestNewInstance { - @Test - public void testLangUtilPkg() { - @SuppressWarnings("rawtypes") - BeansAccess acTm = BeansAccess.get(TreeMap.class); - acTm.newInstance(); - } + @Test + public void testLangUtilPkg() { + @SuppressWarnings("rawtypes") + BeansAccess acTm = BeansAccess.get(TreeMap.class); + acTm.newInstance(); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPriv.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPriv.java index 3dabb6f..5765d65 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPriv.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPriv.java @@ -1,13 +1,13 @@ package net.minidev.asm.bean; public class BBoolPriv { - private boolean value; + private boolean value; - public boolean isValue() { - return value; - } + public boolean isValue() { + return value; + } - public void setValue(boolean value) { - this.value = value; - } + public void setValue(boolean value) { + this.value = value; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPub.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPub.java index e828a09..a4ef3bf 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPub.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BBoolPub.java @@ -1,5 +1,5 @@ package net.minidev.asm.bean; public class BBoolPub { - public boolean value; + public boolean value; } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPriv.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPriv.java index cf0d76c..d6554ee 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPriv.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPriv.java @@ -1,13 +1,13 @@ package net.minidev.asm.bean; public class BBooleanPriv { - private Boolean value; + private Boolean value; - public Boolean getValue() { - return value; - } + public Boolean getValue() { + return value; + } - public void setValue(Boolean value) { - this.value = value; - } + public void setValue(Boolean value) { + this.value = value; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPub.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPub.java index a22ea1d..a8e36fa 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPub.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BBooleanPub.java @@ -1,5 +1,5 @@ package net.minidev.asm.bean; public class BBooleanPub { - public Boolean value; + public Boolean value; } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPriv.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPriv.java index 4602a65..3964bd3 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPriv.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPriv.java @@ -1,13 +1,13 @@ package net.minidev.asm.bean; public class BEnumPriv { - private TEnum value; + private TEnum value; - public TEnum getValue() { - return value; - } + public TEnum getValue() { + return value; + } - public void setValue(TEnum value) { - this.value = value; - } + public void setValue(TEnum value) { + this.value = value; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPrivAc.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPrivAc.java index 738bd7e..7b290a3 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPrivAc.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPrivAc.java @@ -5,48 +5,52 @@ @SuppressWarnings("rawtypes") public class BEnumPrivAc extends BeansAccess { - @Override - public void set(Object object, int methodIndex, Object value) { - if (methodIndex == 0) { - if (value != null) - // value = TEnum.valueOf((String) value); - value = TEnum.valueOf(value.toString()); - ((BEnumPriv) object).setValue((TEnum) value); - return; - } - throw new net.minidev.asm.ex.NoSuchFieldException("mapping BEnumPriv failed to map field:".concat(Integer.toString(methodIndex))); - } + @Override + public void set(Object object, int methodIndex, Object value) { + if (methodIndex == 0) { + if (value != null) + // value = TEnum.valueOf((String) value); + value = TEnum.valueOf(value.toString()); + ((BEnumPriv) object).setValue((TEnum) value); + return; + } + throw new net.minidev.asm.ex.NoSuchFieldException( + "mapping BEnumPriv failed to map field:".concat(Integer.toString(methodIndex))); + } - @Override - public Object get(Object object, int methodIndex) { - if (methodIndex == 0) { - return ((BEnumPriv) object).getValue(); - } - throw new net.minidev.asm.ex.NoSuchFieldException("mapping BEnumPriv failed to map field:".concat(Integer.toString(methodIndex))); - } + @Override + public Object get(Object object, int methodIndex) { + if (methodIndex == 0) { + return ((BEnumPriv) object).getValue(); + } + throw new net.minidev.asm.ex.NoSuchFieldException( + "mapping BEnumPriv failed to map field:".concat(Integer.toString(methodIndex))); + } - @Override - public void set(Object object, String methodIndex, Object value) { - if (methodIndex.equals("value")) { - if (value != null) - // value = TEnum.valueOf((String) value); - value = TEnum.valueOf(value.toString()); - ((BEnumPriv) object).setValue((TEnum) value); - return; - } - throw new net.minidev.asm.ex.NoSuchFieldException("mapping BEnumPriv failed to map field:".concat(methodIndex)); - } + @Override + public void set(Object object, String methodIndex, Object value) { + if (methodIndex.equals("value")) { + if (value != null) + // value = TEnum.valueOf((String) value); + value = TEnum.valueOf(value.toString()); + ((BEnumPriv) object).setValue((TEnum) value); + return; + } + throw new net.minidev.asm.ex.NoSuchFieldException( + "mapping BEnumPriv failed to map field:".concat(methodIndex)); + } - @Override - public Object get(Object object, String methodIndex) { - if (methodIndex.equals("value")) { - return ((BEnumPriv) object).getValue(); - } - throw new net.minidev.asm.ex.NoSuchFieldException("mapping BEnumPriv failed to map field:".concat(methodIndex)); - } + @Override + public Object get(Object object, String methodIndex) { + if (methodIndex.equals("value")) { + return ((BEnumPriv) object).getValue(); + } + throw new net.minidev.asm.ex.NoSuchFieldException( + "mapping BEnumPriv failed to map field:".concat(methodIndex)); + } - @Override - public Object newInstance() { - return new BEnumPriv(); - } + @Override + public Object newInstance() { + return new BEnumPriv(); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPub.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPub.java index 019224e..b153d33 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPub.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BEnumPub.java @@ -1,5 +1,5 @@ package net.minidev.asm.bean; public class BEnumPub { - public TEnum value; + public TEnum value; } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPriv.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPriv.java index 0af71fd..e884e56 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPriv.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPriv.java @@ -1,13 +1,13 @@ package net.minidev.asm.bean; public class BLongPriv { - private Long value; + private Long value; - public Long getValue() { - return value; - } + public Long getValue() { + return value; + } - public void setValue(Long value) { - this.value = value; - } + public void setValue(Long value) { + this.value = value; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPrivAc.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPrivAc.java index 496f9f8..1baee99 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPrivAc.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPrivAc.java @@ -6,41 +6,40 @@ @SuppressWarnings("rawtypes") public class BLongPrivAc extends BeansAccess { - @Override - public void set(Object object, int methodIndex, Object value) { - if (methodIndex == 0) { - ((BLongPriv) object).setValue(DefaultConverter.convertToLong(value)); - return; - } - } - - @Override - public Object get(Object object, int methodIndex) { - if (methodIndex == 0) { - return ((BLongPriv) object).getValue(); - } - return null; - } - - @Override - public void set(Object object, String methodIndex, Object value) { - if (methodIndex.equals("value")) { - ((BLongPriv) object).setValue(DefaultConverter.convertToLong(value)); - return; - } - } - - @Override - public Object get(Object object, String methodIndex) { - if (methodIndex.equals("value")) { - return ((BLongPriv) object).getValue(); - } - return null; - } - - @Override - public Object newInstance() { - return new BLongPriv(); - } - + @Override + public void set(Object object, int methodIndex, Object value) { + if (methodIndex == 0) { + ((BLongPriv) object).setValue(DefaultConverter.convertToLong(value)); + return; + } + } + + @Override + public Object get(Object object, int methodIndex) { + if (methodIndex == 0) { + return ((BLongPriv) object).getValue(); + } + return null; + } + + @Override + public void set(Object object, String methodIndex, Object value) { + if (methodIndex.equals("value")) { + ((BLongPriv) object).setValue(DefaultConverter.convertToLong(value)); + return; + } + } + + @Override + public Object get(Object object, String methodIndex) { + if (methodIndex.equals("value")) { + return ((BLongPriv) object).getValue(); + } + return null; + } + + @Override + public Object newInstance() { + return new BLongPriv(); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPub.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPub.java index 472eb16..0e9e33e 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPub.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPub.java @@ -1,5 +1,5 @@ package net.minidev.asm.bean; public class BLongPub { - public Long value; + public Long value; } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPubAc.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPubAc.java index 7d7fc4b..f1af85a 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPubAc.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BLongPubAc.java @@ -6,41 +6,40 @@ @SuppressWarnings("rawtypes") public class BLongPubAc extends BeansAccess { - @Override - public void set(Object object, int methodIndex, Object value) { - if (methodIndex == 0) { - ((BLongPub) object).value = DefaultConverter.convertToLong(value); - return; - } - } - - @Override - public Object get(Object object, int methodIndex) { - if (methodIndex == 0) { - return ((BLongPub) object).value; - } - return null; - } - - @Override - public void set(Object object, String methodIndex, Object value) { - if (methodIndex.equals("value")) { - ((BLongPub) object).value = DefaultConverter.convertToLong(value); - return; - } - } - - @Override - public Object get(Object object, String methodIndex) { - if (methodIndex.equals("value")) { - return ((BLongPub) object).value; - } - return null; - } - - @Override - public Object newInstance() { - return new BLongPub(); - } - + @Override + public void set(Object object, int methodIndex, Object value) { + if (methodIndex == 0) { + ((BLongPub) object).value = DefaultConverter.convertToLong(value); + return; + } + } + + @Override + public Object get(Object object, int methodIndex) { + if (methodIndex == 0) { + return ((BLongPub) object).value; + } + return null; + } + + @Override + public void set(Object object, String methodIndex, Object value) { + if (methodIndex.equals("value")) { + ((BLongPub) object).value = DefaultConverter.convertToLong(value); + return; + } + } + + @Override + public Object get(Object object, String methodIndex) { + if (methodIndex.equals("value")) { + return ((BLongPub) object).value; + } + return null; + } + + @Override + public Object newInstance() { + return new BLongPub(); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPriv.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPriv.java index ed2d8d6..44dc800 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPriv.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPriv.java @@ -1,13 +1,13 @@ package net.minidev.asm.bean; public class BObjectPriv { - private Object value; + private Object value; - public Object getValue() { - return value; - } + public Object getValue() { + return value; + } - public void setValue(Object value) { - this.value = value; - } + public void setValue(Object value) { + this.value = value; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPub.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPub.java index 8a1a0d3..587d085 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPub.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BObjectPub.java @@ -1,5 +1,5 @@ package net.minidev.asm.bean; public class BObjectPub { - public Object value; + public Object value; } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPriv.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPriv.java index 364fdc2..36a0c00 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPriv.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPriv.java @@ -1,14 +1,13 @@ package net.minidev.asm.bean; public class BStrPriv { - private String value; + private String value; - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPrivAc.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPrivAc.java index fc8c0ed..2cfb100 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPrivAc.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPrivAc.java @@ -5,45 +5,42 @@ @SuppressWarnings("rawtypes") public class BStrPrivAc extends BeansAccess { - @Override - public void set(Object object, int methodIndex, Object value) { - if (methodIndex == 0) { - if (value != null) - value = value.toString(); - ((BStrPriv) object).setValue((String) value); - return; - } - } - - @Override - public Object get(Object object, int methodIndex) { - if (methodIndex == 0) { - return ((BStrPriv) object).getValue(); - } - return null; - } - - @Override - public void set(Object object, String methodIndex, Object value) { - if (methodIndex.equals("value")) { - if (value != null) - value = value.toString(); - ((BStrPriv) object).setValue((String) value); - return; - } - } - - @Override - public Object get(Object object, String methodIndex) { - if (methodIndex.equals("value")) { - return ((BStrPriv) object).getValue(); - } - return null; - } - - @Override - public Object newInstance() { - return new BStrPriv(); - } - + @Override + public void set(Object object, int methodIndex, Object value) { + if (methodIndex == 0) { + if (value != null) value = value.toString(); + ((BStrPriv) object).setValue((String) value); + return; + } + } + + @Override + public Object get(Object object, int methodIndex) { + if (methodIndex == 0) { + return ((BStrPriv) object).getValue(); + } + return null; + } + + @Override + public void set(Object object, String methodIndex, Object value) { + if (methodIndex.equals("value")) { + if (value != null) value = value.toString(); + ((BStrPriv) object).setValue((String) value); + return; + } + } + + @Override + public Object get(Object object, String methodIndex) { + if (methodIndex.equals("value")) { + return ((BStrPriv) object).getValue(); + } + return null; + } + + @Override + public Object newInstance() { + return new BStrPriv(); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPub.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPub.java index b3cf3c0..bf7ec6b 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPub.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPub.java @@ -1,5 +1,5 @@ package net.minidev.asm.bean; public class BStrPub { - public String value; + public String value; } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPubAc.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPubAc.java index 4a4471c..8fc6e92 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPubAc.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BStrPubAc.java @@ -5,45 +5,42 @@ @SuppressWarnings("rawtypes") public class BStrPubAc extends BeansAccess { - @Override - public void set(Object object, int methodIndex, Object value) { - if (methodIndex == 0) { - if (value != null) - value = value.toString(); - ((BStrPub)object).value = (String) value; - return; - } - } - - @Override - public Object get(Object object, int methodIndex) { - if (methodIndex == 0) { - return ((BStrPub)object).value; - } - return null; - } - - @Override - public void set(Object object, String methodIndex, Object value) { - if (methodIndex.equals("value")) { - if (value != null) - value = value.toString(); - ((BStrPub) object).value = (String) value; - return; - } - } - - @Override - public Object get(Object object, String methodIndex) { - if (methodIndex.equals("value")) { - return ((BStrPub) object).value; - } - return null; - } - - @Override - public BStrPub newInstance() { - return new BStrPub(); - } - + @Override + public void set(Object object, int methodIndex, Object value) { + if (methodIndex == 0) { + if (value != null) value = value.toString(); + ((BStrPub) object).value = (String) value; + return; + } + } + + @Override + public Object get(Object object, int methodIndex) { + if (methodIndex == 0) { + return ((BStrPub) object).value; + } + return null; + } + + @Override + public void set(Object object, String methodIndex, Object value) { + if (methodIndex.equals("value")) { + if (value != null) value = value.toString(); + ((BStrPub) object).value = (String) value; + return; + } + } + + @Override + public Object get(Object object, String methodIndex) { + if (methodIndex.equals("value")) { + return ((BStrPub) object).value; + } + return null; + } + + @Override + public BStrPub newInstance() { + return new BStrPub(); + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/BTest.java b/accessors-smart/src/test/java/net/minidev/asm/bean/BTest.java index ef37d5e..0d8ddcd 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/BTest.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/BTest.java @@ -1,33 +1,41 @@ package net.minidev.asm.bean; - public class BTest { - public int pubIntValue; - public String pubStrValue; - private int privIntValue; - private String privStrValue; - public boolean pubBoolValue; - public Integer pubIntegerValue; - public TEnum pubTEnum; - - public void setPrivIntValue(int privIntValue) { - this.privIntValue = privIntValue; - } + public int pubIntValue; + public String pubStrValue; + private int privIntValue; + private String privStrValue; + public boolean pubBoolValue; + public Integer pubIntegerValue; + public TEnum pubTEnum; + + public void setPrivIntValue(int privIntValue) { + this.privIntValue = privIntValue; + } - public int getPrivIntValue() { - return privIntValue; - } + public int getPrivIntValue() { + return privIntValue; + } - public void setPrivStrValue(String privStrValue) { - this.privStrValue = privStrValue; - } + public void setPrivStrValue(String privStrValue) { + this.privStrValue = privStrValue; + } - public String getPrivStrValue() { - return privStrValue; - } + public String getPrivStrValue() { + return privStrValue; + } - public String toString() { - return "Public(i:" + pubIntValue + " s:" + pubStrValue + "B: " + pubBoolValue + ") Private(i:" + privIntValue - + " s:" + privStrValue + ")"; - } + public String toString() { + return "Public(i:" + + pubIntValue + + " s:" + + pubStrValue + + "B: " + + pubBoolValue + + ") Private(i:" + + privIntValue + + " s:" + + privStrValue + + ")"; + } } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/TEnum.java b/accessors-smart/src/test/java/net/minidev/asm/bean/TEnum.java index 001de13..ed9015d 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/TEnum.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/TEnum.java @@ -1,5 +1,7 @@ package net.minidev.asm.bean; public enum TEnum { - V1, V2, V3 + V1, + V2, + V3 } diff --git a/accessors-smart/src/test/java/net/minidev/asm/bean/TestAsmAtom.java b/accessors-smart/src/test/java/net/minidev/asm/bean/TestAsmAtom.java index cf692d5..69e2112 100644 --- a/accessors-smart/src/test/java/net/minidev/asm/bean/TestAsmAtom.java +++ b/accessors-smart/src/test/java/net/minidev/asm/bean/TestAsmAtom.java @@ -2,106 +2,103 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; import net.minidev.asm.BeansAccess; +import org.junit.jupiter.api.Test; public class TestAsmAtom { - @Test - public void testpub() throws Exception { - // int fieldID = 0; - String fieldID = "value"; - { - BeansAccess ac = BeansAccess.get(BStrPub.class); - BStrPub p = ac.newInstance(); - String val = "toto"; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BLongPub.class); - BLongPub p = ac.newInstance(); - Long val = 123L; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BBooleanPub.class); - BBooleanPub p = ac.newInstance(); - Boolean val = Boolean.TRUE; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BBoolPub.class); - BBoolPub p = ac.newInstance(); - Boolean val = Boolean.TRUE; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BEnumPriv.class); - BEnumPriv p = ac.newInstance(); - TEnum val = TEnum.V2; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BObjectPriv.class); - BObjectPriv p = ac.newInstance(); - TEnum val = TEnum.V2; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - - } - - public void testPriv() throws Exception { - // int fieldID = 0; - String fieldID = "value"; - { - BeansAccess ac = BeansAccess.get(BStrPriv.class); - BStrPriv p = ac.newInstance(); - String val = "toto"; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BLongPriv.class); - BLongPriv p = ac.newInstance(); - Long val = 123L; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BBooleanPriv.class); - BBooleanPriv p = ac.newInstance(); - Boolean val = Boolean.TRUE; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BBoolPriv.class); - BBoolPriv p = ac.newInstance(); - Boolean val = Boolean.TRUE; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BEnumPub.class); - BEnumPub p = ac.newInstance(); - TEnum val = TEnum.V2; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - { - BeansAccess ac = BeansAccess.get(BObjectPub.class); - BObjectPub p = ac.newInstance(); - TEnum val = TEnum.V2; - ac.set(p, fieldID, val); - assertEquals(val, ac.get(p, fieldID)); - } - - } + @Test + public void testpub() throws Exception { + // int fieldID = 0; + String fieldID = "value"; + { + BeansAccess ac = BeansAccess.get(BStrPub.class); + BStrPub p = ac.newInstance(); + String val = "toto"; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BLongPub.class); + BLongPub p = ac.newInstance(); + Long val = 123L; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BBooleanPub.class); + BBooleanPub p = ac.newInstance(); + Boolean val = Boolean.TRUE; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BBoolPub.class); + BBoolPub p = ac.newInstance(); + Boolean val = Boolean.TRUE; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BEnumPriv.class); + BEnumPriv p = ac.newInstance(); + TEnum val = TEnum.V2; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BObjectPriv.class); + BObjectPriv p = ac.newInstance(); + TEnum val = TEnum.V2; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + } -} \ No newline at end of file + public void testPriv() throws Exception { + // int fieldID = 0; + String fieldID = "value"; + { + BeansAccess ac = BeansAccess.get(BStrPriv.class); + BStrPriv p = ac.newInstance(); + String val = "toto"; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BLongPriv.class); + BLongPriv p = ac.newInstance(); + Long val = 123L; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BBooleanPriv.class); + BBooleanPriv p = ac.newInstance(); + Boolean val = Boolean.TRUE; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BBoolPriv.class); + BBoolPriv p = ac.newInstance(); + Boolean val = Boolean.TRUE; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BEnumPub.class); + BEnumPub p = ac.newInstance(); + TEnum val = TEnum.V2; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + { + BeansAccess ac = BeansAccess.get(BObjectPub.class); + BObjectPub p = ac.newInstance(); + TEnum val = TEnum.V2; + ac.set(p, fieldID, val); + assertEquals(val, ac.get(p, fieldID)); + } + } +} diff --git a/json-smart-action/pom.xml b/json-smart-action/pom.xml index 4abe7c0..6e4f0bd 100644 --- a/json-smart-action/pom.xml +++ b/json-smart-action/pom.xml @@ -237,11 +237,15 @@ 2.44.2 + + src/main/java/**/*.java + src/test/java/**/*.java + 1.25.2 true - false + true diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/ElementRemover.java b/json-smart-action/src/main/java/net/minidev/json/actions/ElementRemover.java index d34a834..5fda519 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/ElementRemover.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/ElementRemover.java @@ -1,46 +1,50 @@ package net.minidev.json.actions; +import java.util.*; import net.minidev.json.JSONObject; +import net.minidev.json.actions.traverse.JSONTraverseAction; import net.minidev.json.actions.traverse.JSONTraverser; import net.minidev.json.actions.traverse.RemoveElementsJsonAction; -import net.minidev.json.actions.traverse.JSONTraverseAction; - -import java.util.*; /** - * Removes key:value elements from every node of a {@link JSONObject} matching the list of user-specified elements. - *

- * An element to remove must be specified as a key:value pair - *

- * Usage Example: - *

- * To remove the element k2:v2 from the {@link JSONObject} {k0:{k2:v2, k3:v3}, k1:{k2:v2, k4:v4}} use the remover like so: + * Removes key:value elements from every node of a {@link JSONObject} matching the list of + * user-specified elements. + * + *

An element to remove must be specified as a key:value pair + * + *

Usage Example: + * + *

To remove the element k2:v2 from the {@link JSONObject} {k0:{k2:v2, k3:v3}, k1:{k2:v2, k4:v4}} + * use the remover like so: + * *

  * PathRemover pr = new PathRemover("k2.v2");
  * JSONObject cleanObject = pr.remove(new JSONObject(...));
  * 
+ * * The resulting object 'cleanObject' would be {k0:{k3:v3}, k1:{k4:v4}} - *

- * See unit tests for more examples * - * @author adoneitan@gmail.com + *

See unit tests for more examples * + * @author adoneitan@gmail.com */ public class ElementRemover { - private Map elementsToRemove; + private Map elementsToRemove; - public ElementRemover(Map elementsToRemove) { - this.elementsToRemove = elementsToRemove == null ? Collections. emptyMap() : elementsToRemove; - } + public ElementRemover(Map elementsToRemove) { + this.elementsToRemove = + elementsToRemove == null ? Collections.emptyMap() : elementsToRemove; + } - public ElementRemover(JSONObject elementsToRemove) { - this.elementsToRemove = elementsToRemove == null ? Collections. emptyMap() : elementsToRemove; - } + public ElementRemover(JSONObject elementsToRemove) { + this.elementsToRemove = + elementsToRemove == null ? Collections.emptyMap() : elementsToRemove; + } - public JSONObject remove(JSONObject objectToClean) { - JSONTraverseAction strategy = new RemoveElementsJsonAction(this.elementsToRemove); - JSONTraverser traversal = new JSONTraverser(strategy); - traversal.traverse(objectToClean); - return (JSONObject) strategy.result(); - } + public JSONObject remove(JSONObject objectToClean) { + JSONTraverseAction strategy = new RemoveElementsJsonAction(this.elementsToRemove); + JSONTraverser traversal = new JSONTraverser(strategy); + traversal.traverse(objectToClean); + return (JSONObject) strategy.result(); + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/PathLocator.java b/json-smart-action/src/main/java/net/minidev/json/actions/PathLocator.java index c0a9359..c0e1840 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/PathLocator.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/PathLocator.java @@ -1,66 +1,71 @@ package net.minidev.json.actions; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.actions.path.DotDelimiter; import net.minidev.json.actions.path.PathDelimiter; +import net.minidev.json.actions.traverse.JSONTraverseAction; import net.minidev.json.actions.traverse.JSONTraverser; import net.minidev.json.actions.traverse.LocatePathsJsonAction; -import net.minidev.json.actions.traverse.JSONTraverseAction; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; /** * Searches for paths in a {@link JSONObject} and returns those found. - *

- * Traverses the specified {@link JSONObject} searching for nodes whose paths (from the root down) match - * any of the user-specified paths. The paths that match are returned. - *

- * A path to locate must be specified in the n-gram format - a list of keys from the root down separated by dots: - * K0[[[[.K1].K2].K3]...] - *
- * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in their name are - * not supported. + * + *

Traverses the specified {@link JSONObject} searching for nodes whose paths (from the root + * down) match any of the user-specified paths. The paths that match are returned. + * + *

A path to locate must be specified in the n-gram format - a list of keys from the root down + * separated by dots: K0[[[[.K1].K2].K3]...]
+ * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in + * their name are not supported. + * *

* * @author adoneitan@gmail.com */ public class PathLocator { - protected List pathsToFind; - protected PathDelimiter pathDelimiter = new DotDelimiter().withAcceptDelimiterInNodeName(false); + protected List pathsToFind; + protected PathDelimiter pathDelimiter = new DotDelimiter().withAcceptDelimiterInNodeName(false); - public PathLocator(JSONArray pathsToFind) { - if (pathsToFind == null || pathsToFind.isEmpty()) { - this.pathsToFind = Collections.emptyList(); - } else { - this.pathsToFind = new ArrayList(); - for (Object s : pathsToFind) { - this.pathsToFind.add((String) s); - } - } - } + public PathLocator(JSONArray pathsToFind) { + if (pathsToFind == null || pathsToFind.isEmpty()) { + this.pathsToFind = Collections.emptyList(); + } else { + this.pathsToFind = new ArrayList(); + for (Object s : pathsToFind) { + this.pathsToFind.add((String) s); + } + } + } - public PathLocator(List pathsToFind) { - this.pathsToFind = pathsToFind == null || pathsToFind.size() == 0 ? Collections. emptyList() : pathsToFind; - } + public PathLocator(List pathsToFind) { + this.pathsToFind = + pathsToFind == null || pathsToFind.size() == 0 + ? Collections.emptyList() + : pathsToFind; + } - public PathLocator(String... pathsToFind) { - this.pathsToFind = pathsToFind == null || pathsToFind.length == 0 ? Collections. emptyList() : Arrays.asList(pathsToFind); - } + public PathLocator(String... pathsToFind) { + this.pathsToFind = + pathsToFind == null || pathsToFind.length == 0 + ? Collections.emptyList() + : Arrays.asList(pathsToFind); + } - public PathLocator with(PathDelimiter pathDelimiter) { - this.pathDelimiter = pathDelimiter; - return this; - } + public PathLocator with(PathDelimiter pathDelimiter) { + this.pathDelimiter = pathDelimiter; + return this; + } - @SuppressWarnings("unchecked") - public List locate(JSONObject object) { - JSONTraverseAction action = new LocatePathsJsonAction(this.pathsToFind, pathDelimiter); - JSONTraverser traversal = new JSONTraverser(action).with(pathDelimiter); - traversal.traverse(object); - return (List) action.result(); - } + @SuppressWarnings("unchecked") + public List locate(JSONObject object) { + JSONTraverseAction action = new LocatePathsJsonAction(this.pathsToFind, pathDelimiter); + JSONTraverser traversal = new JSONTraverser(action).with(pathDelimiter); + traversal.traverse(object); + return (List) action.result(); + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/PathRemover.java b/json-smart-action/src/main/java/net/minidev/json/actions/PathRemover.java index af486e3..3ea6927 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/PathRemover.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/PathRemover.java @@ -1,65 +1,72 @@ package net.minidev.json.actions; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONObject; -import net.minidev.json.actions.traverse.JSONTraverser; -import net.minidev.json.actions.traverse.RemovePathsJsonAction; -import net.minidev.json.actions.traverse.JSONTraverseAction; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import net.minidev.json.actions.traverse.JSONTraverseAction; +import net.minidev.json.actions.traverse.JSONTraverser; +import net.minidev.json.actions.traverse.RemovePathsJsonAction; /** - * Removes branches of nodes from a {@link JSONObject} matching the list of user-specified paths. - *

- * A path to remove must be specified in the n-gram format - a list of keys from the root down separated by dots: - * K0[[[[.K1].K2].K3]...] - *
- * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in their name are - * not supported. - *

- * Usage Example: - *

- * To remove the field k1.k2 from the {@link JSONObject} {k1:{k2:v2}, k3:{k4:v4}} use the remover like so: + * Removes branches of nodes from a {@link JSONObject} matching the list of user-specified + * paths. + * + *

A path to remove must be specified in the n-gram format - a list of keys from the root down + * separated by dots: K0[[[[.K1].K2].K3]...]
+ * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in + * their name are not supported. + * + *

Usage Example: + * + *

To remove the field k1.k2 from the {@link JSONObject} {k1:{k2:v2}, k3:{k4:v4}} use the remover + * like so: + * *

  * PathRemover pr = new PathRemover("k1.k2");
  * JSONObject cleanObject = pr.remove(new JSONObject(...));
  * 
+ * * The resulting object 'cleanObject' would be {k1:{k3:{k4:v4}}} - *

- * See unit tests for more examples * - * @author adoneitan@gmail.com + *

See unit tests for more examples * + * @author adoneitan@gmail.com */ public class PathRemover { - protected List pathsToRemove; + protected List pathsToRemove; - public PathRemover(JSONArray pathsToRemove) { - if (pathsToRemove == null || pathsToRemove.isEmpty()) { - this.pathsToRemove = Collections.emptyList(); - } else { - this.pathsToRemove = new ArrayList(); - for (Object s : pathsToRemove) { - this.pathsToRemove.add((String) s); - } - } - } + public PathRemover(JSONArray pathsToRemove) { + if (pathsToRemove == null || pathsToRemove.isEmpty()) { + this.pathsToRemove = Collections.emptyList(); + } else { + this.pathsToRemove = new ArrayList(); + for (Object s : pathsToRemove) { + this.pathsToRemove.add((String) s); + } + } + } - public PathRemover(List pathsToRemove) { - this.pathsToRemove = pathsToRemove == null || pathsToRemove.size() == 0 ? Collections. emptyList() : pathsToRemove; - } + public PathRemover(List pathsToRemove) { + this.pathsToRemove = + pathsToRemove == null || pathsToRemove.size() == 0 + ? Collections.emptyList() + : pathsToRemove; + } - public PathRemover(String... pathsToRemove) { - this.pathsToRemove = pathsToRemove == null || pathsToRemove.length == 0 ? Collections. emptyList() : Arrays.asList(pathsToRemove); - } + public PathRemover(String... pathsToRemove) { + this.pathsToRemove = + pathsToRemove == null || pathsToRemove.length == 0 + ? Collections.emptyList() + : Arrays.asList(pathsToRemove); + } - public JSONObject remove(JSONObject objectToClean) { - JSONTraverseAction strategy = new RemovePathsJsonAction(this.pathsToRemove); - JSONTraverser traversal = new JSONTraverser(strategy); - traversal.traverse(objectToClean); - return (JSONObject) strategy.result(); - } + public JSONObject remove(JSONObject objectToClean) { + JSONTraverseAction strategy = new RemovePathsJsonAction(this.pathsToRemove); + JSONTraverser traversal = new JSONTraverser(strategy); + traversal.traverse(objectToClean); + return (JSONObject) strategy.result(); + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/PathReplicator.java b/json-smart-action/src/main/java/net/minidev/json/actions/PathReplicator.java index 3841c94..d5b8f21 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/PathReplicator.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/PathReplicator.java @@ -1,68 +1,75 @@ package net.minidev.json.actions; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONObject; -import net.minidev.json.actions.navigate.CopyPathsAction; -import net.minidev.json.actions.navigate.JSONNavigator; - import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import net.minidev.json.actions.navigate.CopyPathsAction; +import net.minidev.json.actions.navigate.JSONNavigator; /** - * Creates a copy of a {@link JSONObject} consisting only of the nodes on the user-specified paths. - *

- * Paths that do not exist in the specified object are ignored silently. Specifying an empty list of paths - * to copy or only non-existent paths will result in an empty object being returned. - *

- * A path to copy must be specified in the n-gram format - a list of keys from the root down separated by dots: - * K0[[[[.K1].K2].K3]...] - *
- * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in their name are - * not supported. - *

- * Sample usage: - *

- * To replicate the branch k1.k2 from {k1:{k2:v2}, k3:{k4:v4}} use the {@link PathReplicator} like so: + * Creates a copy of a {@link JSONObject} consisting only of the nodes on the user-specified + * paths. + * + *

Paths that do not exist in the specified object are ignored silently. Specifying an empty list + * of paths to copy or only non-existent paths will result in an empty object being returned. + * + *

A path to copy must be specified in the n-gram format - a list of keys from the root down + * separated by dots: K0[[[[.K1].K2].K3]...]
+ * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in + * their name are not supported. + * + *

Sample usage: + * + *

To replicate the branch k1.k2 from {k1:{k2:v2}, k3:{k4:v4}} use the {@link PathReplicator} + * like so: + * *

  * PathReplicator pr = new {@link PathReplicator}("k1.k2")
  * JSONObject copiedObject = pr.copy(new JSONObject(...))
  * 
+ * * The resulting object 'copiedObject' would be {k1:{k2:v2}} - *

- * see unit tests for more examples + * + *

see unit tests for more examples * * @author adoneitan@gmail.com * @since 15 March 2016. */ public class PathReplicator { - protected List pathsToCopy; + protected List pathsToCopy; - public PathReplicator(JSONArray pathsToCopy) { - if (pathsToCopy == null || pathsToCopy.isEmpty()) { - this.pathsToCopy = Collections.emptyList(); - } else { - this.pathsToCopy = new LinkedList(); - for (Object s : pathsToCopy) { - this.pathsToCopy.add((String) s); - } - } - } + public PathReplicator(JSONArray pathsToCopy) { + if (pathsToCopy == null || pathsToCopy.isEmpty()) { + this.pathsToCopy = Collections.emptyList(); + } else { + this.pathsToCopy = new LinkedList(); + for (Object s : pathsToCopy) { + this.pathsToCopy.add((String) s); + } + } + } - public PathReplicator(List pathsToCopy) { - this.pathsToCopy = pathsToCopy == null || pathsToCopy.size() == 0 ? Collections. emptyList() : pathsToCopy; - } + public PathReplicator(List pathsToCopy) { + this.pathsToCopy = + pathsToCopy == null || pathsToCopy.size() == 0 + ? Collections.emptyList() + : pathsToCopy; + } - public PathReplicator(String... pathsToCopy) { - this.pathsToCopy = pathsToCopy == null || pathsToCopy.length == 0 ? Collections. emptyList() - : new LinkedList(Arrays.asList(pathsToCopy)); - } + public PathReplicator(String... pathsToCopy) { + this.pathsToCopy = + pathsToCopy == null || pathsToCopy.length == 0 + ? Collections.emptyList() + : new LinkedList(Arrays.asList(pathsToCopy)); + } - public JSONObject replicate(JSONObject sourceObj) throws Exception { - CopyPathsAction s = new CopyPathsAction(); - JSONNavigator n = new JSONNavigator(s, pathsToCopy); - n.nav(sourceObj); - return (JSONObject) s.result(); - } + public JSONObject replicate(JSONObject sourceObj) throws Exception { + CopyPathsAction s = new CopyPathsAction(); + JSONNavigator n = new JSONNavigator(s, pathsToCopy); + n.nav(sourceObj); + return (JSONObject) s.result(); + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/PathsRetainer.java b/json-smart-action/src/main/java/net/minidev/json/actions/PathsRetainer.java index 013baa8..824d884 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/PathsRetainer.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/PathsRetainer.java @@ -1,5 +1,9 @@ package net.minidev.json.actions; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.actions.path.DotDelimiter; @@ -9,78 +13,76 @@ import net.minidev.json.actions.traverse.LocatePathsJsonAction; import net.minidev.json.actions.traverse.RetainPathsJsonAction; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - /** - * Retains branches of nodes of a {@link JSONObject} matching the list of user-specified paths. - *

- * A path to copy must be specified in the n-gram format - a list of keys from the root down separated by dots: - * K0[[[[.K1].K2].K3]...] - *
- * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in their name are - * not supported. - *

- * Example: - *

- * to retain the field k1.k2 in the {@link JSONObject} {k1:{k2:v1}, k3:{k4:v2}} instantiate the retainer like so: - * new JSONObjectCleaner("k1.k2") - * The resulting object would be {k1:{k2:v1}} - *

- * See unit tests in JSONObjectRetainerTest for more examples + * Retains branches of nodes of a {@link JSONObject} matching the list of user-specified + * paths. + * + *

A path to copy must be specified in the n-gram format - a list of keys from the root down + * separated by dots: K0[[[[.K1].K2].K3]...]
+ * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in + * their name are not supported. + * + *

Example: + * + *

to retain the field k1.k2 in the {@link JSONObject} {k1:{k2:v1}, k3:{k4:v2}} instantiate the + * retainer like so: new JSONObjectCleaner("k1.k2") The resulting object would be {k1:{k2:v1}} + * + *

See unit tests in JSONObjectRetainerTest for more examples * * @author adoneitan@gmail.com */ public class PathsRetainer { - protected List pathsToRetain; - protected PathDelimiter pathDelimiter = new DotDelimiter().withAcceptDelimiterInNodeName(false); + protected List pathsToRetain; + protected PathDelimiter pathDelimiter = new DotDelimiter().withAcceptDelimiterInNodeName(false); - public PathsRetainer(JSONArray pathsToRetain) { - if (pathsToRetain == null || pathsToRetain.isEmpty()) { - this.pathsToRetain = Collections.emptyList(); - } else { - this.pathsToRetain = new LinkedList(); - for (Object s : pathsToRetain) { - this.pathsToRetain.add((String) s); - } - } - } + public PathsRetainer(JSONArray pathsToRetain) { + if (pathsToRetain == null || pathsToRetain.isEmpty()) { + this.pathsToRetain = Collections.emptyList(); + } else { + this.pathsToRetain = new LinkedList(); + for (Object s : pathsToRetain) { + this.pathsToRetain.add((String) s); + } + } + } - public PathsRetainer(List pathsToRetain) { - this.pathsToRetain = pathsToRetain == null || pathsToRetain.size() == 0 ? Collections. emptyList() : pathsToRetain; - } + public PathsRetainer(List pathsToRetain) { + this.pathsToRetain = + pathsToRetain == null || pathsToRetain.size() == 0 + ? Collections.emptyList() + : pathsToRetain; + } - public PathsRetainer(String... pathsToRetain) { - this.pathsToRetain = pathsToRetain == null || pathsToRetain.length == 0 ? Collections. emptyList() - : new LinkedList(Arrays.asList(pathsToRetain)); - } + public PathsRetainer(String... pathsToRetain) { + this.pathsToRetain = + pathsToRetain == null || pathsToRetain.length == 0 + ? Collections.emptyList() + : new LinkedList(Arrays.asList(pathsToRetain)); + } - public PathsRetainer with(PathDelimiter pathDelimiter) { - this.pathDelimiter = pathDelimiter; - return this; - } + public PathsRetainer with(PathDelimiter pathDelimiter) { + this.pathDelimiter = pathDelimiter; + return this; + } - @SuppressWarnings("unchecked") - public JSONObject retain(JSONObject object) { - /** - * a path to retain which contains a path in the object, but is not itself a path in the object, - * will cause the sub-path to be retained although it shouldn't: - * object = {k0:v0} retain = {k0.k1} - * so the false path to retain has to be removed from the pathsToRetain list. - * - * The {@link LocatePathsJsonAction} returns only paths which exist in the object. - */ - JSONTraverseAction locateAction = new LocatePathsJsonAction(pathsToRetain, pathDelimiter); - JSONTraverser t1 = new JSONTraverser(locateAction); - t1.traverse(object); - List realPathsToRetain = (List) locateAction.result(); + @SuppressWarnings("unchecked") + public JSONObject retain(JSONObject object) { + /** + * a path to retain which contains a path in the object, but is not itself a path in the object, + * will cause the sub-path to be retained although it shouldn't: object = {k0:v0} retain = + * {k0.k1} so the false path to retain has to be removed from the pathsToRetain list. + * + *

The {@link LocatePathsJsonAction} returns only paths which exist in the object. + */ + JSONTraverseAction locateAction = new LocatePathsJsonAction(pathsToRetain, pathDelimiter); + JSONTraverser t1 = new JSONTraverser(locateAction); + t1.traverse(object); + List realPathsToRetain = (List) locateAction.result(); - //now reduce the object using only existing paths - JSONTraverseAction retainer = new RetainPathsJsonAction(realPathsToRetain, pathDelimiter); - JSONTraverser t2 = new JSONTraverser(retainer).with(pathDelimiter); - t2.traverse(object); - return (JSONObject) retainer.result(); - } + // now reduce the object using only existing paths + JSONTraverseAction retainer = new RetainPathsJsonAction(realPathsToRetain, pathDelimiter); + JSONTraverser t2 = new JSONTraverser(retainer).with(pathDelimiter); + t2.traverse(object); + return (JSONObject) retainer.result(); + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/CopyPathsAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/CopyPathsAction.java index 26e32a3..f292bc9 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/CopyPathsAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/CopyPathsAction.java @@ -1,137 +1,134 @@ package net.minidev.json.actions.navigate; +import java.util.Collection; +import java.util.Stack; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.actions.path.TreePath; -import java.util.Collection; -import java.util.Stack; - /** * Creates a copy of a {@link JSONObject} containing just the nodes on the paths specified. - *

- * Specified paths that do not exist in the source object are ignored silently. - * Specifying an empty list of paths to navigate or only non-existent paths will result in an empty - * object being returned. - *

- * See package-info for more details - *

- * Example: - *

- * To copy the branch k1.k2 from {k1:{k2:v1}, k3:{k4:v2}} instantiate the copier like so: - * new JSONObjectCopier("k1.k2") - * The resulting copy would be {k1:{k2:v1}} - *

- * See unit tests for more examples + * + *

Specified paths that do not exist in the source object are ignored silently. Specifying an + * empty list of paths to navigate or only non-existent paths will result in an empty object being + * returned. + * + *

See package-info for more details + * + *

Example: + * + *

To copy the branch k1.k2 from {k1:{k2:v1}, k3:{k4:v2}} instantiate the copier like so: new + * JSONObjectCopier("k1.k2") The resulting copy would be {k1:{k2:v1}} + * + *

See unit tests for more examples * * @author adoneitan@gmail.com * @since 15 March 2016. - * */ public class CopyPathsAction implements JSONNavigateAction { - protected JSONObject destTree; - protected JSONObject destBranch; - protected Stack destNodeStack; - - @Override - public boolean start(JSONObject source, Collection pathsToCopy) { - if (source == null) { - destTree = null; - return false; - } - destTree = new JSONObject(); - if (pathsToCopy == null || pathsToCopy.size() == 0) { - return false; - } - return true; - } - - @Override - public boolean recurInto(TreePath jp, JSONObject o) { - //reached JSONObject node - instantiate it and recur - handleNewNode(jp, new JSONObject()); - return true; - } - - private void handleNewNode(TreePath jp, Object node) { - if (!jp.hasPrev()) { - return; - } - if (destNodeStack.peek() instanceof JSONObject) { - ((JSONObject) destNodeStack.peek()).put(jp.curr(), node); - } else if (destNodeStack.peek() instanceof JSONArray) { - ((JSONArray) destNodeStack.peek()).add(node); - } - destNodeStack.push(node); - } - - @Override - public boolean recurInto(TreePath jp, JSONArray o) { - //reached JSONArray node - instantiate it and recur - handleNewNode(jp, new JSONArray()); - return true; - } - - @Override - public void foundLeafBeforePathEnd(TreePath jp, Object obj) { - throw new IllegalArgumentException("branch is shorter than path - path not found in source: '" + jp.origin() + "'"); - } - - @Override - public void pathTailNotFound(TreePath jp, Object source) { - throw new IllegalArgumentException("cannot find next element of path - path not found in source: '" + jp.origin() + "'"); - } - - @Override - public void handleLeaf(TreePath jp, Object o) { - ((JSONObject) destNodeStack.peek()).put(jp.curr(), o); - } - - @Override - public void handleLeaf(TreePath jp, int arrIndex, Object o) { - ((JSONArray) destNodeStack.peek()).add(o); - } - - @Override - public void recurEnd(TreePath jp, JSONObject jo) { - destNodeStack.pop(); - } - - @Override - public void recurEnd(TreePath jp, JSONArray ja) { - destNodeStack.pop(); - } - - @Override - public boolean pathStart(String path) { - destBranch = new JSONObject(); - destNodeStack = new Stack(); - destNodeStack.push(destBranch); - return true; - } - - @Override - public void pathEnd(String path) { - destTree.merge(destBranch); - } - - @Override - public boolean failSilently(String path, Exception e) { - return false; - } - - @Override - public boolean failFast(String path, Exception e) { - return false; - } - - @Override - public void end() { - - } - - @Override - public Object result() { - return destTree; - } + protected JSONObject destTree; + protected JSONObject destBranch; + protected Stack destNodeStack; + + @Override + public boolean start(JSONObject source, Collection pathsToCopy) { + if (source == null) { + destTree = null; + return false; + } + destTree = new JSONObject(); + if (pathsToCopy == null || pathsToCopy.size() == 0) { + return false; + } + return true; + } + + @Override + public boolean recurInto(TreePath jp, JSONObject o) { + // reached JSONObject node - instantiate it and recur + handleNewNode(jp, new JSONObject()); + return true; + } + + private void handleNewNode(TreePath jp, Object node) { + if (!jp.hasPrev()) { + return; + } + if (destNodeStack.peek() instanceof JSONObject) { + ((JSONObject) destNodeStack.peek()).put(jp.curr(), node); + } else if (destNodeStack.peek() instanceof JSONArray) { + ((JSONArray) destNodeStack.peek()).add(node); + } + destNodeStack.push(node); + } + + @Override + public boolean recurInto(TreePath jp, JSONArray o) { + // reached JSONArray node - instantiate it and recur + handleNewNode(jp, new JSONArray()); + return true; + } + + @Override + public void foundLeafBeforePathEnd(TreePath jp, Object obj) { + throw new IllegalArgumentException( + "branch is shorter than path - path not found in source: '" + jp.origin() + "'"); + } + + @Override + public void pathTailNotFound(TreePath jp, Object source) { + throw new IllegalArgumentException( + "cannot find next element of path - path not found in source: '" + jp.origin() + "'"); + } + + @Override + public void handleLeaf(TreePath jp, Object o) { + ((JSONObject) destNodeStack.peek()).put(jp.curr(), o); + } + + @Override + public void handleLeaf(TreePath jp, int arrIndex, Object o) { + ((JSONArray) destNodeStack.peek()).add(o); + } + + @Override + public void recurEnd(TreePath jp, JSONObject jo) { + destNodeStack.pop(); + } + + @Override + public void recurEnd(TreePath jp, JSONArray ja) { + destNodeStack.pop(); + } + + @Override + public boolean pathStart(String path) { + destBranch = new JSONObject(); + destNodeStack = new Stack(); + destNodeStack.push(destBranch); + return true; + } + + @Override + public void pathEnd(String path) { + destTree.merge(destBranch); + } + + @Override + public boolean failSilently(String path, Exception e) { + return false; + } + + @Override + public boolean failFast(String path, Exception e) { + return false; + } + + @Override + public void end() {} + + @Override + public Object result() { + return destTree; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigateAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigateAction.java index c274e59..f06a6ca 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigateAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigateAction.java @@ -4,13 +4,12 @@ import net.minidev.json.JSONObject; /** - * An interface for a processing action on the nodes of a {@link JSONObject} while navigating its branches. - *

- * See package-info for more details + * An interface for a processing action on the nodes of a {@link JSONObject} while navigating its + * branches. + * + *

See package-info for more details * * @author adoneitan@gmail.com * @since 15 June 2016. */ -public interface JSONNavigateAction extends NavigateAction { - -} +public interface JSONNavigateAction extends NavigateAction {} diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigator.java b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigator.java index e2f60a2..79fab41 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigator.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/JSONNavigator.java @@ -1,21 +1,20 @@ package net.minidev.json.actions.navigate; +import java.util.List; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; -import java.util.List; - /** * @author adoneitan@gmail.com * @since 15 June 2016. */ public class JSONNavigator extends TreeNavigator { - public JSONNavigator(JSONNavigateAction action, List pathsToNavigate) { - super(action, pathsToNavigate); - } + public JSONNavigator(JSONNavigateAction action, List pathsToNavigate) { + super(action, pathsToNavigate); + } - public JSONNavigator(JSONNavigateAction action, String... pathsToNavigate) { - super(action, pathsToNavigate); - } + public JSONNavigator(JSONNavigateAction action, String... pathsToNavigate) { + super(action, pathsToNavigate); + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/NavigateAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/NavigateAction.java index f637da0..592b700 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/NavigateAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/NavigateAction.java @@ -1,139 +1,139 @@ package net.minidev.json.actions.navigate; -import net.minidev.json.actions.path.TreePath; - import java.util.Collection; import java.util.List; import java.util.Map; +import net.minidev.json.actions.path.TreePath; /** * An interface for a processing action on the nodes of a {@link M} while navigating its branches. - *

- * See package-info for more details + * + *

See package-info for more details * * @author adoneitan@gmail.com * @since 15 June 2016 */ public interface NavigateAction, L extends List> { - /** - * called before navigation of a new path starts - * @param path TODO - * @return true if the specified path should be navigated - */ - boolean pathStart(String path); - - /** - * called before any navigation of the {@link M} starts - * - * @param objectToNavigate TODO - * @param pathsToNavigate TODO - * - * @return true if navigation should start at all - */ - boolean start(M objectToNavigate, Collection pathsToNavigate); - - /** - * reached end of branch in source before end of specified path - - * the specified path does not exist in the source - * - * @param tp TODO - * @param source TODO - */ - void pathTailNotFound(TreePath tp, Object source); - - /** - * called after the navigation of a path ends - * - * @param path TODO - */ - void pathEnd(String path); - - /** - * called if navigation of a path throws an exception - * - * @param path TODO - * @param e TODO - * @return true if the failure on this path should not abort the rest of the navigation - */ - boolean failSilently(String path, Exception e); - - /** - * called if navigation of a path throws an exception - * - * @param path TODO - * @param e TODO - * @return true if the failure on this path should abort the rest of the navigation - */ - boolean failFast(String path, Exception e); - - /** - * called when an object node is encountered on the path - * - * @param tp TODO - * @param sourceNode TODO - * @return true if the navigator should navigate into the object - */ - boolean recurInto(TreePath tp, M sourceNode); - - /** - * called when an array node is encountered on the path - * - * @param tp TODO - * @param sourceNode TODO - * @return true if the navigator should navigate into the array - */ - boolean recurInto(TreePath tp, L sourceNode); - - /** - * reached leaf node (not a container) in source but specified path expects children - - * the specified path does not exist in the source - * @param jp TODO - * @param obj TODO - */ - void foundLeafBeforePathEnd(TreePath jp, Object obj); - - /** - * called when a leaf node is reached in a M. - * a leaf in a M is a key-value pair where the value is not a container itself - * (it is not a M nor a L) - * @param tp - the JsonPath pointing to the leaf - * @param value TODO - */ - void handleLeaf(TreePath tp, Object value); - - /** - * called when a leaf in a L is reached. - * a leaf in a L is a non-container item - * (it is not a M nor a L) - * @param tp - - * @param arrIndex - - * @param arrItem - the item - */ - void handleLeaf(TreePath tp, int arrIndex, Object arrItem); - - /** - * called when navigation of an {@link M} type object ends - * @param tp the path pointing to the object - * @param m TODO - */ - void recurEnd(TreePath tp, M m); - - /** - * called when navigation of an {@link L} type object ends - * @param tp the path pointing to the object - * @param l TODO - */ - void recurEnd(TreePath tp, L l); - - /** - * called after all navigation ends, and just before the navigation method exits - */ - void end(); - - /** - * holds the result of the navigation, as assigned by the action implementing this interface - * @return - result - */ - Object result(); - + /** + * called before navigation of a new path starts + * + * @param path TODO + * @return true if the specified path should be navigated + */ + boolean pathStart(String path); + + /** + * called before any navigation of the {@link M} starts + * + * @param objectToNavigate TODO + * @param pathsToNavigate TODO + * @return true if navigation should start at all + */ + boolean start(M objectToNavigate, Collection pathsToNavigate); + + /** + * reached end of branch in source before end of specified path - the specified path does not + * exist in the source + * + * @param tp TODO + * @param source TODO + */ + void pathTailNotFound(TreePath tp, Object source); + + /** + * called after the navigation of a path ends + * + * @param path TODO + */ + void pathEnd(String path); + + /** + * called if navigation of a path throws an exception + * + * @param path TODO + * @param e TODO + * @return true if the failure on this path should not abort the rest of the navigation + */ + boolean failSilently(String path, Exception e); + + /** + * called if navigation of a path throws an exception + * + * @param path TODO + * @param e TODO + * @return true if the failure on this path should abort the rest of the navigation + */ + boolean failFast(String path, Exception e); + + /** + * called when an object node is encountered on the path + * + * @param tp TODO + * @param sourceNode TODO + * @return true if the navigator should navigate into the object + */ + boolean recurInto(TreePath tp, M sourceNode); + + /** + * called when an array node is encountered on the path + * + * @param tp TODO + * @param sourceNode TODO + * @return true if the navigator should navigate into the array + */ + boolean recurInto(TreePath tp, L sourceNode); + + /** + * reached leaf node (not a container) in source but specified path expects children - the + * specified path does not exist in the source + * + * @param jp TODO + * @param obj TODO + */ + void foundLeafBeforePathEnd(TreePath jp, Object obj); + + /** + * called when a leaf node is reached in a M. a leaf in a M is a key-value pair where the value is + * not a container itself (it is not a M nor a L) + * + * @param tp - the JsonPath pointing to the leaf + * @param value TODO + */ + void handleLeaf(TreePath tp, Object value); + + /** + * called when a leaf in a L is reached. a leaf in a L is a non-container item (it is not a M nor + * a L) + * + * @param tp - + * @param arrIndex - + * @param arrItem - the item + */ + void handleLeaf(TreePath tp, int arrIndex, Object arrItem); + + /** + * called when navigation of an {@link M} type object ends + * + * @param tp the path pointing to the object + * @param m TODO + */ + void recurEnd(TreePath tp, M m); + + /** + * called when navigation of an {@link L} type object ends + * + * @param tp the path pointing to the object + * @param l TODO + */ + void recurEnd(TreePath tp, L l); + + /** called after all navigation ends, and just before the navigation method exits */ + void end(); + + /** + * holds the result of the navigation, as assigned by the action implementing this interface + * + * @return - result + */ + Object result(); } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/TreeNavigator.java b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/TreeNavigator.java index 4d60353..6363679 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/TreeNavigator.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/TreeNavigator.java @@ -1,138 +1,137 @@ package net.minidev.json.actions.navigate; -import net.minidev.json.JSONObject; -import net.minidev.json.actions.path.DotDelimiter; -import net.minidev.json.actions.path.TreePath; - import java.util.Arrays; import java.util.List; import java.util.Map; +import net.minidev.json.JSONObject; +import net.minidev.json.actions.path.DotDelimiter; +import net.minidev.json.actions.path.TreePath; /** * Navigates only the branches of a {@link JSONObject} corresponding to the paths specified. - *

- * For each specified path to navigate, the {@link TreeNavigator} only traverses the matching + * + *

For each specified path to navigate, the {@link TreeNavigator} only traverses the matching * branch. - *

- * The navigator accepts an action and provides callback hooks for it to act on the traversed + * + *

The navigator accepts an action and provides callback hooks for it to act on the traversed * nodes at each significant step. See {@link NavigateAction}. - *

- * See package-info for more details - *

- * Example: - *

- * To navigate the branch k1.k2 of the object {"k1":{"k2":"v1"}, "k3":{"k4":"v2"}} instantiate + * + *

See package-info for more details + * + *

Example: + * + *

To navigate the branch k1.k2 of the object {"k1":{"k2":"v1"}, "k3":{"k4":"v2"}} instantiate * the navigator like so: new JSONNavigator("k1.k2") * * @author adoneitan@gmail.com * @since 15 June 2016. - * */ public class TreeNavigator, L extends List> { - protected List pathsToNavigate; - protected NavigateAction action; - protected String pathPrefix = ""; + protected List pathsToNavigate; + protected NavigateAction action; + protected String pathPrefix = ""; - public TreeNavigator(NavigateAction action, List pathsToNavigate) { - if (action == null) { - throw new IllegalArgumentException("NavigateAction cannot be null"); - } - this.action = action; - this.pathsToNavigate = pathsToNavigate; - } + public TreeNavigator(NavigateAction action, List pathsToNavigate) { + if (action == null) { + throw new IllegalArgumentException("NavigateAction cannot be null"); + } + this.action = action; + this.pathsToNavigate = pathsToNavigate; + } - public TreeNavigator with(String pathPrefix) { - this.pathPrefix = pathPrefix; - return this; - } + public TreeNavigator with(String pathPrefix) { + this.pathPrefix = pathPrefix; + return this; + } - public TreeNavigator(NavigateAction action, String... pathsToNavigate) { - this(action, Arrays.asList(pathsToNavigate)); - } + public TreeNavigator(NavigateAction action, String... pathsToNavigate) { + this(action, Arrays.asList(pathsToNavigate)); + } - public void nav(M object) throws Exception { - if (action.start(object, pathsToNavigate)) { - for (String path : pathsToNavigate) { - try { - if (path != null && !path.equals("") && action.pathStart(path)) { - TreePath jp = new TreePath(path, new DotDelimiter().withAcceptDelimiterInNodeName(true)); - nav(jp, object); - action.pathEnd(path); - } - } catch (Exception e) { - if (action.failSilently(path, e)) { - break; - } else if (action.failFast(path, e)) { - throw e; - } - } - } - } - action.end(); - } + public void nav(M object) throws Exception { + if (action.start(object, pathsToNavigate)) { + for (String path : pathsToNavigate) { + try { + if (path != null && !path.equals("") && action.pathStart(path)) { + TreePath jp = + new TreePath(path, new DotDelimiter().withAcceptDelimiterInNodeName(true)); + nav(jp, object); + action.pathEnd(path); + } + } catch (Exception e) { + if (action.failSilently(path, e)) { + break; + } else if (action.failFast(path, e)) { + throw e; + } + } + } + } + action.end(); + } - @SuppressWarnings("unchecked") - public void nav(TreePath jp, M map) { - if (map == null || !action.recurInto(jp, map)) { - //source is null - navigation impossible - return; - } + @SuppressWarnings("unchecked") + public void nav(TreePath jp, M map) { + if (map == null || !action.recurInto(jp, map)) { + // source is null - navigation impossible + return; + } - if (jp.hasNext()) { - String key = jp.next(); - if (!map.containsKey(key)) { - // cannot find next element of path in the source - - // the specified path does not exist in the source - action.pathTailNotFound(jp, map); - } else if (map.get(key) instanceof Map) { - //reached Map type node - handle it and recur into it - nav(jp, (M) map.get(key)); - } else if (map.get(key) instanceof List) { - //reached List type node - handle it and recur into it - nav(jp, (L) map.get(key)); - } else if (jp.hasNext()) { - // reached leaf node (not a container) in source but specified path expects children - - // the specified path is illegal because it does not exist in the source. - action.foundLeafBeforePathEnd(jp, map.get(key)); - } else if (!jp.hasNext()) { - //reached leaf in source and specified path is also at leaf -> handle it - action.handleLeaf(jp, map.get(key)); - } else { - throw new IllegalStateException("fatal: unreachable code reached at '" + jp.origin() + "'"); - } - } - action.recurEnd(jp, (M) map); - } + if (jp.hasNext()) { + String key = jp.next(); + if (!map.containsKey(key)) { + // cannot find next element of path in the source - + // the specified path does not exist in the source + action.pathTailNotFound(jp, map); + } else if (map.get(key) instanceof Map) { + // reached Map type node - handle it and recur into it + nav(jp, (M) map.get(key)); + } else if (map.get(key) instanceof List) { + // reached List type node - handle it and recur into it + nav(jp, (L) map.get(key)); + } else if (jp.hasNext()) { + // reached leaf node (not a container) in source but specified path expects children - + // the specified path is illegal because it does not exist in the source. + action.foundLeafBeforePathEnd(jp, map.get(key)); + } else if (!jp.hasNext()) { + // reached leaf in source and specified path is also at leaf -> handle it + action.handleLeaf(jp, map.get(key)); + } else { + throw new IllegalStateException("fatal: unreachable code reached at '" + jp.origin() + "'"); + } + } + action.recurEnd(jp, (M) map); + } - @SuppressWarnings("unchecked") - public void nav(TreePath jp, L list) { - if (list == null || !action.recurInto(jp, (L) list)) { - //list is null - navigation impossible - return; - } - int arrIndex = 0; - for (Object arrItem : list.toArray()) { - if (arrItem instanceof Map) { - // clone the path so that for each object in the array, - // the iterator continues from the same position in the path - TreePath jpClone = getClone(jp); - nav(jpClone, (M) arrItem); - } else if (arrItem instanceof List) { - nav(jp, (L) arrItem); - } else if (!jp.hasNext()) { - //reached leaf - handle it - action.handleLeaf(jp, arrIndex, arrItem); - } - arrIndex++; - } - action.recurEnd(jp, (L) list); - } + @SuppressWarnings("unchecked") + public void nav(TreePath jp, L list) { + if (list == null || !action.recurInto(jp, (L) list)) { + // list is null - navigation impossible + return; + } + int arrIndex = 0; + for (Object arrItem : list.toArray()) { + if (arrItem instanceof Map) { + // clone the path so that for each object in the array, + // the iterator continues from the same position in the path + TreePath jpClone = getClone(jp); + nav(jpClone, (M) arrItem); + } else if (arrItem instanceof List) { + nav(jp, (L) arrItem); + } else if (!jp.hasNext()) { + // reached leaf - handle it + action.handleLeaf(jp, arrIndex, arrItem); + } + arrIndex++; + } + action.recurEnd(jp, (L) list); + } - private TreePath getClone(TreePath jp) { - try { - return jp.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException("failed to clone path", e); - } - } + private TreePath getClone(TreePath jp) { + try { + return jp.clone(); + } catch (CloneNotSupportedException e) { + throw new RuntimeException("failed to clone path", e); + } + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/package-info.java b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/package-info.java index 40727e4..37af138 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/navigate/package-info.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/navigate/package-info.java @@ -1,21 +1,23 @@ /** - * Navigate user-specified paths in a tree made up of {@link java.util.Map}s and {@link java.util.List} and process them - *

- * {@link net.minidev.json.actions.navigate.TreeNavigator} only navigates through branches corresponding - * to user-specified paths. For each path, the navigation starts at the root and moves down the branch. - *

- * The {@link net.minidev.json.actions.navigate.TreeNavigator} accepts a - * {@link net.minidev.json.actions.navigate.NavigateAction} and provides callback hooks at each significant - * step which the {@link net.minidev.json.actions.navigate.NavigateAction} may use to process - * the nodes. - *

- * A path to navigate must be specified in the n-gram format - a list of keys from the root down separated by dots: - * K0[[[[.K1].K2].K3]...] - *
- * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in their name are - * not supported. - *

- * Sample usage: + * Navigate user-specified paths in a tree made up of {@link java.util.Map}s and {@link + * java.util.List} and process them + * + *

{@link net.minidev.json.actions.navigate.TreeNavigator} only navigates through branches + * corresponding to user-specified paths. For each path, the navigation starts at the root and moves + * down the branch. + * + *

The {@link net.minidev.json.actions.navigate.TreeNavigator} accepts a {@link + * net.minidev.json.actions.navigate.NavigateAction} and provides callback hooks at each significant + * step which the {@link net.minidev.json.actions.navigate.NavigateAction} may use to process the + * nodes. + * + *

A path to navigate must be specified in the n-gram format - a list of keys from the root down + * separated by dots: K0[[[[.K1].K2].K3]...]
+ * A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot in + * their name are not supported. + * + *

Sample usage: + * *

  * NavigateAction navAction = new NavigateAction(){...};
  * JSONNavigator jsonNav = new JSONNavigator(navAction, "foo.bar.path");
@@ -25,4 +27,4 @@
  *
  * @author adoneitan@gmail.com
  */
-package net.minidev.json.actions.navigate;
\ No newline at end of file
+package net.minidev.json.actions.navigate;
diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/path/DotDelimiter.java b/json-smart-action/src/main/java/net/minidev/json/actions/path/DotDelimiter.java
index e20a1f2..dc4c519 100644
--- a/json-smart-action/src/main/java/net/minidev/json/actions/path/DotDelimiter.java
+++ b/json-smart-action/src/main/java/net/minidev/json/actions/path/DotDelimiter.java
@@ -1,20 +1,20 @@
 package net.minidev.json.actions.path;
 
 /**
- * Encapsulates the delimiter '.' of the path parts when the path is specified in n-gram format.
- * For example: root.node1.node11.leaf
+ * Encapsulates the delimiter '.' of the path parts when the path is specified in n-gram format. For
+ * example: root.node1.node11.leaf
  *
  * @author adoneitan@gmail.com
  * @since 31 May2016
  */
 public class DotDelimiter extends PathDelimiter {
-	protected static final char DELIM_CHAR = '.';
+  protected static final char DELIM_CHAR = '.';
 
-	public DotDelimiter() {
-		super(DELIM_CHAR);
-	}
+  public DotDelimiter() {
+    super(DELIM_CHAR);
+  }
 
-	public String regex() {
-		return "\\.";
-	}
+  public String regex() {
+    return "\\.";
+  }
 }
diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/path/PathDelimiter.java b/json-smart-action/src/main/java/net/minidev/json/actions/path/PathDelimiter.java
index b22fea8..db8e495 100644
--- a/json-smart-action/src/main/java/net/minidev/json/actions/path/PathDelimiter.java
+++ b/json-smart-action/src/main/java/net/minidev/json/actions/path/PathDelimiter.java
@@ -7,34 +7,32 @@
  * @since 31 May 2016
  */
 public abstract class PathDelimiter {
-	protected char delimChar;
-	protected String delimStr;
-	protected boolean acceptDelimInKey;
-
-	public PathDelimiter(char delim) {
-		this.delimChar = delim;
-		this.delimStr = String.valueOf(delim);
-	}
-
-	public PathDelimiter withAcceptDelimiterInNodeName(boolean acceptDelimInKey) {
-		this.acceptDelimInKey = acceptDelimInKey;
-		return this;
-	}
-
-	public boolean accept(String key) {
-		if (!acceptDelimInKey && key.contains(delimStr))
-			return false;
-		return true;
-	}
-
-	public String str() {
-		return delimStr;
-	}
-
-	public char chr() {
-		return delimChar;
-	}
-
-	public abstract String regex();
-
+  protected char delimChar;
+  protected String delimStr;
+  protected boolean acceptDelimInKey;
+
+  public PathDelimiter(char delim) {
+    this.delimChar = delim;
+    this.delimStr = String.valueOf(delim);
+  }
+
+  public PathDelimiter withAcceptDelimiterInNodeName(boolean acceptDelimInKey) {
+    this.acceptDelimInKey = acceptDelimInKey;
+    return this;
+  }
+
+  public boolean accept(String key) {
+    if (!acceptDelimInKey && key.contains(delimStr)) return false;
+    return true;
+  }
+
+  public String str() {
+    return delimStr;
+  }
+
+  public char chr() {
+    return delimChar;
+  }
+
+  public abstract String regex();
 }
diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/path/SlashDelimiter.java b/json-smart-action/src/main/java/net/minidev/json/actions/path/SlashDelimiter.java
index 7a341a9..13e1dfc 100644
--- a/json-smart-action/src/main/java/net/minidev/json/actions/path/SlashDelimiter.java
+++ b/json-smart-action/src/main/java/net/minidev/json/actions/path/SlashDelimiter.java
@@ -1,21 +1,21 @@
 package net.minidev.json.actions.path;
 
 /**
- * Encapsulates the delimiter '.' of the path parts when the path is specified in n-gram format.
- * For example: root.node1.node11.leaf
+ * Encapsulates the delimiter '.' of the path parts when the path is specified in n-gram format. For
+ * example: root.node1.node11.leaf
  *
  * @author adoneitan@gmail.com
  * @since 31 May 2016
  */
 public class SlashDelimiter extends PathDelimiter {
-	protected static final char DELIM_CHAR = '/';
+  protected static final char DELIM_CHAR = '/';
 
-	public SlashDelimiter() {
-		super(DELIM_CHAR);
-		super.withAcceptDelimiterInNodeName(false);
-	}
+  public SlashDelimiter() {
+    super(DELIM_CHAR);
+    super.withAcceptDelimiterInNodeName(false);
+  }
 
-	public String regex() {
-		return "\\/";
-	}
+  public String regex() {
+    return "\\/";
+  }
 }
diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/path/TreePath.java b/json-smart-action/src/main/java/net/minidev/json/actions/path/TreePath.java
index 64d996e..cd4476f 100644
--- a/json-smart-action/src/main/java/net/minidev/json/actions/path/TreePath.java
+++ b/json-smart-action/src/main/java/net/minidev/json/actions/path/TreePath.java
@@ -1,232 +1,236 @@
 package net.minidev.json.actions.path;
 
 import java.util.Arrays;
-import java.util.Map;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Map;
 
 /**
- * {@link TreePath} represents an n-gram formatted path
- * corresponding to a branch in a tree of {@link Map}s
- * and {@link List}s
- * 

- * See package-info for more details + * {@link TreePath} represents an n-gram formatted path corresponding to a branch in a tree of + * {@link Map}s and {@link List}s + * + *

See package-info for more details * * @author adoneitan@gmail.com */ public class TreePath { - protected enum Step { - NONE, NEXT, PREV - } - - protected final String path; - protected List keys; - protected ListIterator keysItr; - protected String currKey; - protected Step lastStep; - protected StringBuilder origin; - protected StringBuilder remainder; - protected PathDelimiter delim; - - public TreePath(String path, PathDelimiter delim) { - this.delim = delim; - checkPath(path); - this.path = path; - this.keys = Arrays.asList(path.split(delim.regex())); - reset(); - } - - public void reset() { - keysItr = keys.listIterator(); - currKey = ""; - lastStep = Step.NONE; - origin = new StringBuilder(""); - remainder = new StringBuilder(path); - } - - public boolean hasNext() { - return keysItr.hasNext(); - } - - public int nextIndex() { - return keysItr.nextIndex(); - } - - public String next() { - currKey = keysItr.next(); - /** when changing direction the {@link ListIterator} does not really - * move backward so an extra step is performed */ - if (!lastStep.equals(Step.PREV)) { - originIncrement(); - remainderDecrement(); - } - lastStep = Step.NEXT; - return currKey; - } - - public boolean hasPrev() { - return keysItr.hasPrevious(); - } - - public int prevIndex() { - return keysItr.previousIndex(); - } - - public String prev() { - String temp = currKey; - currKey = keysItr.previous(); - /** when changing direction the {@link ListIterator} does not really - * move backward so an extra step is performed */ - if (!lastStep.equals(Step.NEXT)) { - remainderIncrement(temp); - originDecrement(); - } - lastStep = Step.PREV; - return currKey; - } - - private void remainderDecrement() { - if (length() == 1) - remainder = new StringBuilder(""); - else if (remainder.indexOf(delim.str()) < 0) - remainder = new StringBuilder(""); - else - remainder.delete(0, remainder.indexOf(delim.str()) + 1); - } - - private void originDecrement() { - if (length() == 1) - origin = new StringBuilder(""); - else if (origin.indexOf(delim.str()) < 0) - origin = new StringBuilder(""); - else - origin.delete(origin.lastIndexOf(delim.str()), origin.length()); - } - - private void originIncrement() { - if (origin.length() != 0) { - origin.append(delim.chr()); - } - origin.append(currKey); - } - - private void remainderIncrement(String prev) { - if (remainder.length() == 0) - remainder = new StringBuilder(prev); - else - remainder = new StringBuilder(prev).append(delim.chr()).append(remainder); - } - - /** - * @return An n-gram path from the first key to the current key (inclusive) - */ - public String path() { - return path; - } - - /** - * @return An n-gram path from the first key to the current key (inclusive) - */ - public String origin() { - return origin.toString(); - } - - /** - * @return An n-gram path from the current key to the last key (inclusive) - */ - public String remainder() { - return remainder.toString(); - } - - /** - * @return first element in the JSONPath - */ - public String first() { - return keys.get(0); - } - - /** - * @return last element in the JSONPath - */ - public String last() { - return keys.get(keys.size() - 1); - } - - /** - * @return current element pointed to by the path iterator - */ - public String curr() { - return currKey; - } - - public int length() { - return keys.size(); - } - - public String subPath(int firstIndex, int lastIndex) { - if (lastIndex < firstIndex) { - throw new IllegalArgumentException("bad call to subPath"); - } - StringBuilder sb = new StringBuilder(path.length()); - for (int i = firstIndex; i <= lastIndex; i++) { - sb.append(keys.get(i)); - if (i < lastIndex) { - sb.append(delim.chr()); - } - } - sb.trimToSize(); - return sb.toString(); - } - - private void checkPath(String path) { - if (path == null || path.equals("")) - throw new IllegalArgumentException("path cannot be null or empty"); - if (path.startsWith(delim.str()) || path.endsWith(delim.str()) || path.contains(delim.str() + delim.str())) - throw new IllegalArgumentException(String.format("path cannot start or end with %s or contain '%s%s'", delim.str(), delim.str(), delim.str())); - } - - @Override - public TreePath clone() throws CloneNotSupportedException { - TreePath cloned = new TreePath(this.path, this.delim); - while (cloned.nextIndex() != this.nextIndex()) { - cloned.next(); - } - if (cloned.prevIndex() != this.prevIndex()) { - cloned.prev(); - } - cloned.lastStep = this.lastStep; - cloned.currKey = new String(this.currKey); - cloned.origin = new StringBuilder(this.origin); - cloned.remainder = new StringBuilder(this.remainder); - return cloned; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - TreePath treePath = (TreePath) o; - - return path().equals(treePath.path()) && hasNext() == treePath.hasNext() && hasPrev() == treePath.hasPrev() && curr().equals(treePath.curr()) - && origin().equals(treePath.origin()) && remainder().equals(treePath.remainder()) && lastStep == treePath.lastStep - && delim.equals(treePath.delim); - - } - - @Override - public int hashCode() { - int result = path.hashCode(); - result = 31 * result + keys.hashCode(); - result = 31 * result + keysItr.hashCode(); - result = 31 * result + currKey.hashCode(); - result = 31 * result + lastStep.hashCode(); - result = 31 * result + origin.hashCode(); - result = 31 * result + remainder.hashCode(); - result = 31 * result + delim.hashCode(); - return result; - } + protected enum Step { + NONE, + NEXT, + PREV + } + + protected final String path; + protected List keys; + protected ListIterator keysItr; + protected String currKey; + protected Step lastStep; + protected StringBuilder origin; + protected StringBuilder remainder; + protected PathDelimiter delim; + + public TreePath(String path, PathDelimiter delim) { + this.delim = delim; + checkPath(path); + this.path = path; + this.keys = Arrays.asList(path.split(delim.regex())); + reset(); + } + + public void reset() { + keysItr = keys.listIterator(); + currKey = ""; + lastStep = Step.NONE; + origin = new StringBuilder(""); + remainder = new StringBuilder(path); + } + + public boolean hasNext() { + return keysItr.hasNext(); + } + + public int nextIndex() { + return keysItr.nextIndex(); + } + + public String next() { + currKey = keysItr.next(); + /** + * when changing direction the {@link ListIterator} does not really move backward so an extra + * step is performed + */ + if (!lastStep.equals(Step.PREV)) { + originIncrement(); + remainderDecrement(); + } + lastStep = Step.NEXT; + return currKey; + } + + public boolean hasPrev() { + return keysItr.hasPrevious(); + } + + public int prevIndex() { + return keysItr.previousIndex(); + } + + public String prev() { + String temp = currKey; + currKey = keysItr.previous(); + /** + * when changing direction the {@link ListIterator} does not really move backward so an extra + * step is performed + */ + if (!lastStep.equals(Step.NEXT)) { + remainderIncrement(temp); + originDecrement(); + } + lastStep = Step.PREV; + return currKey; + } + + private void remainderDecrement() { + if (length() == 1) remainder = new StringBuilder(""); + else if (remainder.indexOf(delim.str()) < 0) remainder = new StringBuilder(""); + else remainder.delete(0, remainder.indexOf(delim.str()) + 1); + } + + private void originDecrement() { + if (length() == 1) origin = new StringBuilder(""); + else if (origin.indexOf(delim.str()) < 0) origin = new StringBuilder(""); + else origin.delete(origin.lastIndexOf(delim.str()), origin.length()); + } + + private void originIncrement() { + if (origin.length() != 0) { + origin.append(delim.chr()); + } + origin.append(currKey); + } + + private void remainderIncrement(String prev) { + if (remainder.length() == 0) remainder = new StringBuilder(prev); + else remainder = new StringBuilder(prev).append(delim.chr()).append(remainder); + } + + /** + * @return An n-gram path from the first key to the current key (inclusive) + */ + public String path() { + return path; + } + + /** + * @return An n-gram path from the first key to the current key (inclusive) + */ + public String origin() { + return origin.toString(); + } + + /** + * @return An n-gram path from the current key to the last key (inclusive) + */ + public String remainder() { + return remainder.toString(); + } + + /** + * @return first element in the JSONPath + */ + public String first() { + return keys.get(0); + } + + /** + * @return last element in the JSONPath + */ + public String last() { + return keys.get(keys.size() - 1); + } + + /** + * @return current element pointed to by the path iterator + */ + public String curr() { + return currKey; + } + + public int length() { + return keys.size(); + } + + public String subPath(int firstIndex, int lastIndex) { + if (lastIndex < firstIndex) { + throw new IllegalArgumentException("bad call to subPath"); + } + StringBuilder sb = new StringBuilder(path.length()); + for (int i = firstIndex; i <= lastIndex; i++) { + sb.append(keys.get(i)); + if (i < lastIndex) { + sb.append(delim.chr()); + } + } + sb.trimToSize(); + return sb.toString(); + } + + private void checkPath(String path) { + if (path == null || path.equals("")) + throw new IllegalArgumentException("path cannot be null or empty"); + if (path.startsWith(delim.str()) + || path.endsWith(delim.str()) + || path.contains(delim.str() + delim.str())) + throw new IllegalArgumentException( + String.format( + "path cannot start or end with %s or contain '%s%s'", + delim.str(), delim.str(), delim.str())); + } + + @Override + public TreePath clone() throws CloneNotSupportedException { + TreePath cloned = new TreePath(this.path, this.delim); + while (cloned.nextIndex() != this.nextIndex()) { + cloned.next(); + } + if (cloned.prevIndex() != this.prevIndex()) { + cloned.prev(); + } + cloned.lastStep = this.lastStep; + cloned.currKey = new String(this.currKey); + cloned.origin = new StringBuilder(this.origin); + cloned.remainder = new StringBuilder(this.remainder); + return cloned; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TreePath treePath = (TreePath) o; + + return path().equals(treePath.path()) + && hasNext() == treePath.hasNext() + && hasPrev() == treePath.hasPrev() + && curr().equals(treePath.curr()) + && origin().equals(treePath.origin()) + && remainder().equals(treePath.remainder()) + && lastStep == treePath.lastStep + && delim.equals(treePath.delim); + } + + @Override + public int hashCode() { + int result = path.hashCode(); + result = 31 * result + keys.hashCode(); + result = 31 * result + keysItr.hashCode(); + result = 31 * result + currKey.hashCode(); + result = 31 * result + lastStep.hashCode(); + result = 31 * result + origin.hashCode(); + result = 31 * result + remainder.hashCode(); + result = 31 * result + delim.hashCode(); + return result; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverseAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverseAction.java index 11c6151..e713215 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverseAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverseAction.java @@ -5,10 +5,9 @@ /** * An interface for a processing action on the nodes of a {@link JSONObject} while traversing it. - *

- * See package-info for more details + * + *

See package-info for more details * * @author adoneitan@gmail.com */ -public interface JSONTraverseAction extends TreeTraverseAction { -} +public interface JSONTraverseAction extends TreeTraverseAction {} diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverser.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverser.java index 506526c..18bcc30 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverser.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/JSONTraverser.java @@ -7,25 +7,24 @@ /** * Traverses every node of a {@link JSONObject} - *

- * {@link JSONTraverser} accepts an action and provides callback hooks for it to act - * on the traversed nodes at each significant step. See {@link JSONTraverseAction}. - *

- * A key to the right of a dot is a direct child of a key to the left of a dot. - * Keys with a dot in their name are not supported. - *

- * See package-info for more details * - * @author adoneitan@gmail.com + *

{@link JSONTraverser} accepts an action and provides callback hooks for it to act on the + * traversed nodes at each significant step. See {@link JSONTraverseAction}. + * + *

A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot + * in their name are not supported. * + *

See package-info for more details + * + * @author adoneitan@gmail.com */ public class JSONTraverser extends TreeTraverser { - public JSONTraverser(JSONTraverseAction action) { - super(action, new DotDelimiter()); - } + public JSONTraverser(JSONTraverseAction action) { + super(action, new DotDelimiter()); + } - public JSONTraverser with(PathDelimiter delim) { - super.delim = delim; - return this; - } + public JSONTraverser with(PathDelimiter delim) { + super.delim = delim; + return this; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/KeysPrintAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/KeysPrintAction.java index e19c74d..70825de 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/KeysPrintAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/KeysPrintAction.java @@ -1,59 +1,51 @@ package net.minidev.json.actions.traverse; +import java.util.Map.Entry; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; -import java.util.Map.Entry; - /** * @author adoneitan@gmail.com - * @since 5/24/16. + * @since 5/24/16. */ public class KeysPrintAction implements JSONTraverseAction { - @Override - public boolean start(JSONObject object) { - return true; - } - - @Override - public boolean traverseEntry(String fullPathToEntry, Entry entry) { - // System.out.println(entry.getKey()); - return true; - } - - @Override - public boolean recurInto(String pathToEntry, JSONObject entryValue) { - return true; - } - - @Override - public boolean recurInto(String pathToEntry, JSONArray entryValue) { - return true; - } - - @Override - public void handleLeaf(String pathToEntry, Entry entry) { - - } - - @Override - public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) { - - } - - @Override - public boolean removeEntry(String fullPathToEntry, Entry entry) { - return false; - } - - @Override - public void end() { - - } - - @Override - public Object result() { - return null; - } - + @Override + public boolean start(JSONObject object) { + return true; + } + + @Override + public boolean traverseEntry(String fullPathToEntry, Entry entry) { + // System.out.println(entry.getKey()); + return true; + } + + @Override + public boolean recurInto(String pathToEntry, JSONObject entryValue) { + return true; + } + + @Override + public boolean recurInto(String pathToEntry, JSONArray entryValue) { + return true; + } + + @Override + public void handleLeaf(String pathToEntry, Entry entry) {} + + @Override + public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) {} + + @Override + public boolean removeEntry(String fullPathToEntry, Entry entry) { + return false; + } + + @Override + public void end() {} + + @Override + public Object result() { + return null; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/LocatePathsJsonAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/LocatePathsJsonAction.java index 300e276..8ee6e4f 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/LocatePathsJsonAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/LocatePathsJsonAction.java @@ -1,96 +1,89 @@ package net.minidev.json.actions.traverse; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONObject; -import net.minidev.json.actions.path.PathDelimiter; - import java.util.LinkedList; import java.util.List; import java.util.Map.Entry; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import net.minidev.json.actions.path.PathDelimiter; /** * Searches for paths in a {@link JSONObject} and returns those found - *

- * A path is not removed from the user-specified list once its processing is over, - * because identical objects in the same array are supported by this action. - *

- * See package-info for more details - *

- * See unit tests for examples * - * @author adoneitan@gmail.com + *

A path is not removed from the user-specified list once its processing is over, because + * identical objects in the same array are supported by this action. + * + *

See package-info for more details * + *

See unit tests for examples + * + * @author adoneitan@gmail.com */ public class LocatePathsJsonAction implements JSONTraverseAction { - protected List pathsFound; - protected List pathsToFind; - protected PathDelimiter delim; - - /** - * - * @param pathsToFind - * A path to a field in the {@link JSONObject} should be specified in n-gram format where keys are chained: k0[[[.k1].k2]...] - * @param delim - - */ - public LocatePathsJsonAction(List pathsToFind, PathDelimiter delim) { - this.pathsToFind = pathsToFind; - this.delim = delim; - pathsFound = new LinkedList(); - } - - @Override - public boolean start(JSONObject object) { - return object != null && pathsToFind != null && pathsToFind.size() > 0; - } - - @Override - public boolean traverseEntry(String fullPathToEntry, Entry entry) { - if (!delim.accept(entry.getKey())) { - return false; - } - locatePath(fullPathToEntry); - return true; - } - - @Override - public boolean recurInto(String pathToEntry, JSONObject entryValue) { - return true; - } - - @Override - public boolean recurInto(String pathToEntry, JSONArray entryValue) { - return true; - } - - @Override - public void handleLeaf(String pathToEntry, Entry entry) { - - } - - @Override - public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) { - - } - - @Override - public boolean removeEntry(String fullPathToEntry, Entry entry) { - return false; - } - - @Override - public void end() { - // nothing to do - } - - @Override - public Object result() { - return pathsFound; - } - - private void locatePath(String pathToEntry) { - if (pathsToFind.contains(pathToEntry)) { - // reached end of path that is being searched - pathsFound.add(pathToEntry); - } - } + protected List pathsFound; + protected List pathsToFind; + protected PathDelimiter delim; + + /** + * @param pathsToFind A path to a field in the {@link JSONObject} should be specified in n-gram + * format where keys are chained: k0[[[.k1].k2]...] + * @param delim - + */ + public LocatePathsJsonAction(List pathsToFind, PathDelimiter delim) { + this.pathsToFind = pathsToFind; + this.delim = delim; + pathsFound = new LinkedList(); + } + + @Override + public boolean start(JSONObject object) { + return object != null && pathsToFind != null && pathsToFind.size() > 0; + } + + @Override + public boolean traverseEntry(String fullPathToEntry, Entry entry) { + if (!delim.accept(entry.getKey())) { + return false; + } + locatePath(fullPathToEntry); + return true; + } + + @Override + public boolean recurInto(String pathToEntry, JSONObject entryValue) { + return true; + } + + @Override + public boolean recurInto(String pathToEntry, JSONArray entryValue) { + return true; + } + + @Override + public void handleLeaf(String pathToEntry, Entry entry) {} + + @Override + public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) {} + + @Override + public boolean removeEntry(String fullPathToEntry, Entry entry) { + return false; + } + + @Override + public void end() { + // nothing to do + } + + @Override + public Object result() { + return pathsFound; + } + + private void locatePath(String pathToEntry) { + if (pathsToFind.contains(pathToEntry)) { + // reached end of path that is being searched + pathsFound.add(pathToEntry); + } + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemoveElementsJsonAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemoveElementsJsonAction.java index 9965d72..8a412e3 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemoveElementsJsonAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemoveElementsJsonAction.java @@ -1,81 +1,76 @@ package net.minidev.json.actions.traverse; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONObject; - import java.util.Map; import java.util.Map.Entry; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; /** * Removes key:value elements from a {@link JSONObject}. - *

- * An element is not removed from the user-specified list once its processing is over, - * because it may appear in more than one node. - *

- * See package-info for more details - *

- * See unit tests for examples * - * @author adoneitan@gmail.com + *

An element is not removed from the user-specified list once its processing is over, because it + * may appear in more than one node. + * + *

See package-info for more details + * + *

See unit tests for examples * + * @author adoneitan@gmail.com */ public class RemoveElementsJsonAction implements JSONTraverseAction { - protected JSONObject result; - protected final Map elementsToRemove; - protected final boolean allowDotChar; - - public RemoveElementsJsonAction(Map elementsToRemove, boolean allowDotChar) { - this.elementsToRemove = elementsToRemove; - this.allowDotChar = allowDotChar; - } + protected JSONObject result; + protected final Map elementsToRemove; + protected final boolean allowDotChar; - public RemoveElementsJsonAction(Map elementsToRemove) { - this(elementsToRemove, false); - } + public RemoveElementsJsonAction(Map elementsToRemove, boolean allowDotChar) { + this.elementsToRemove = elementsToRemove; + this.allowDotChar = allowDotChar; + } - @Override - public boolean start(JSONObject object) { - result = object; - return object != null && elementsToRemove != null && elementsToRemove.size() > 0; - } + public RemoveElementsJsonAction(Map elementsToRemove) { + this(elementsToRemove, false); + } - @Override - public boolean removeEntry(String fullPathToEntry, Entry entry) { - return elementsToRemove.entrySet().contains(entry); - } + @Override + public boolean start(JSONObject object) { + result = object; + return object != null && elementsToRemove != null && elementsToRemove.size() > 0; + } - @Override - public boolean traverseEntry(String fullPathToEntry, Entry entry) { - // must traverse the whole object - return true; - } + @Override + public boolean removeEntry(String fullPathToEntry, Entry entry) { + return elementsToRemove.entrySet().contains(entry); + } - @Override - public boolean recurInto(String pathToEntry, JSONObject entryValue) { - return true; - } + @Override + public boolean traverseEntry(String fullPathToEntry, Entry entry) { + // must traverse the whole object + return true; + } - @Override - public boolean recurInto(String pathToEntry, JSONArray entryValue) { - return true; - } + @Override + public boolean recurInto(String pathToEntry, JSONObject entryValue) { + return true; + } - @Override - public void handleLeaf(String pathToEntry, Entry entry) { - } + @Override + public boolean recurInto(String pathToEntry, JSONArray entryValue) { + return true; + } - @Override - public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) { + @Override + public void handleLeaf(String pathToEntry, Entry entry) {} - } + @Override + public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) {} - @Override - public void end() { - // nothing to do - } + @Override + public void end() { + // nothing to do + } - @Override - public Object result() { - return result; - } + @Override + public Object result() { + return result; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemovePathsJsonAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemovePathsJsonAction.java index e5983af..0087214 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemovePathsJsonAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RemovePathsJsonAction.java @@ -1,76 +1,70 @@ package net.minidev.json.actions.traverse; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONObject; - import java.util.List; import java.util.Map.Entry; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; /** * Removes branches from a {@link JSONObject}. - *

- * A path is not removed from the user-specified list once its processing is over, - * because identical objects in the same array are supported by this action. - *

- * See package-info for more details - *

- * See unit tests for examples * - * @author adoneitan@gmail.com + *

A path is not removed from the user-specified list once its processing is over, because + * identical objects in the same array are supported by this action. * + *

See package-info for more details + * + *

See unit tests for examples + * + * @author adoneitan@gmail.com */ public class RemovePathsJsonAction implements JSONTraverseAction { - protected JSONObject result; - protected List pathsToRemove; - - public RemovePathsJsonAction(List pathsToRemove) { - this.pathsToRemove = pathsToRemove; - } - - @Override - public boolean start(JSONObject object) { - result = object; - return object != null && pathsToRemove != null && pathsToRemove.size() > 0; - } + protected JSONObject result; + protected List pathsToRemove; - @Override - public boolean removeEntry(String fullPathToEntry, Entry entry) { - return pathsToRemove.contains(fullPathToEntry); - } + public RemovePathsJsonAction(List pathsToRemove) { + this.pathsToRemove = pathsToRemove; + } - @Override - public boolean traverseEntry(String fullPathToEntry, Entry entry) { - // must traverse the whole object - return true; - } + @Override + public boolean start(JSONObject object) { + result = object; + return object != null && pathsToRemove != null && pathsToRemove.size() > 0; + } - @Override - public boolean recurInto(String pathToEntry, JSONObject entryValue) { - return true; - } + @Override + public boolean removeEntry(String fullPathToEntry, Entry entry) { + return pathsToRemove.contains(fullPathToEntry); + } - @Override - public boolean recurInto(String pathToEntry, JSONArray entryValue) { - return true; - } + @Override + public boolean traverseEntry(String fullPathToEntry, Entry entry) { + // must traverse the whole object + return true; + } - @Override - public void handleLeaf(String pathToEntry, Entry entry) { + @Override + public boolean recurInto(String pathToEntry, JSONObject entryValue) { + return true; + } - } + @Override + public boolean recurInto(String pathToEntry, JSONArray entryValue) { + return true; + } - @Override - public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) { + @Override + public void handleLeaf(String pathToEntry, Entry entry) {} - } + @Override + public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) {} - @Override - public void end() { - // nothing to do - } + @Override + public void end() { + // nothing to do + } - @Override - public Object result() { - return result; - } + @Override + public Object result() { + return result; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RetainPathsJsonAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RetainPathsJsonAction.java index 9dbe5bb..f4dec63 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RetainPathsJsonAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/RetainPathsJsonAction.java @@ -1,131 +1,118 @@ package net.minidev.json.actions.traverse; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONObject; -import net.minidev.json.actions.path.PathDelimiter; - import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import net.minidev.json.actions.path.PathDelimiter; /** * Retain branches or parts of branches matching a specified list of paths. - *

- * Paths are matched from the root down. If a user-specified path ends at a non-leaf node, - * the rest of the branch from that node to the leaf is not retained. - *

- * A path is not removed from the user-specified list once its processing is over, - * because identical objects in the same array are supported by this action. - *

- * See package-info for more details - *

- * See unit tests for examples * - * @author adoneitan@gmail.com + *

Paths are matched from the root down. If a user-specified path ends at a non-leaf node, the + * rest of the branch from that node to the leaf is not retained. + * + *

A path is not removed from the user-specified list once its processing is over, because + * identical objects in the same array are supported by this action. * + *

See package-info for more details + * + *

See unit tests for examples + * + * @author adoneitan@gmail.com */ -public class RetainPathsJsonAction implements JSONTraverseAction -{ - protected final PathDelimiter delim; - protected JSONObject result; - protected List pathsToRetain; +public class RetainPathsJsonAction implements JSONTraverseAction { + protected final PathDelimiter delim; + protected JSONObject result; + protected List pathsToRetain; - /** - * @param pathsToRetain TODO - * @param delim TODO - */ - public RetainPathsJsonAction(List pathsToRetain, PathDelimiter delim) - { - this.pathsToRetain = new ArrayList(pathsToRetain); - this.delim = delim; - } + /** + * @param pathsToRetain TODO + * @param delim TODO + */ + public RetainPathsJsonAction(List pathsToRetain, PathDelimiter delim) { + this.pathsToRetain = new ArrayList(pathsToRetain); + this.delim = delim; + } - @Override - public boolean start(JSONObject object) - { - if (object == null) - { - result = null; - return false; - } - if (pathsToRetain == null || pathsToRetain.size() == 0) - { - result = new JSONObject(); - return false; - } - result = object; - return true; - } + @Override + public boolean start(JSONObject object) { + if (object == null) { + result = null; + return false; + } + if (pathsToRetain == null || pathsToRetain.size() == 0) { + result = new JSONObject(); + return false; + } + result = object; + return true; + } - @Override - public boolean traverseEntry(String fullPathToEntry, Entry entry) { - return true; - } + @Override + public boolean traverseEntry(String fullPathToEntry, Entry entry) { + return true; + } - @Override - public boolean recurInto(String fullPathToSubtree, JSONObject entryValue) { - return true; - } + @Override + public boolean recurInto(String fullPathToSubtree, JSONObject entryValue) { + return true; + } - @Override - public boolean recurInto(String fullPathToArrayItem, JSONArray entryValue) { - return true; - } + @Override + public boolean recurInto(String fullPathToArrayItem, JSONArray entryValue) { + return true; + } - @Override - public void handleLeaf(String pathToEntry, Entry entry) { - } + @Override + public void handleLeaf(String pathToEntry, Entry entry) {} - @Override - public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) { - } + @Override + public void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem) {} - @Override - public boolean removeEntry(String fullPathToEntry, Entry entry) { - return discardPath(fullPathToEntry, entry); - } + @Override + public boolean removeEntry(String fullPathToEntry, Entry entry) { + return discardPath(fullPathToEntry, entry); + } - @Override - public void end() - { - // nothing to do - } + @Override + public void end() { + // nothing to do + } - @Override - public Object result() { - return result; - } + @Override + public Object result() { + return result; + } - /** - * if the full path to the entry is not contained in any of the paths to retain - remove it from the object - * this step does not remove entries whose full path is contained in a path to retain but are not equal to an - * entry to retain - * - * @param pathToEntry TODO - * @param entry TODO - * @return TODO - */ - protected boolean discardPath(String pathToEntry, Entry entry) - { - if (!foundAsPrefix(pathToEntry) || !delim.accept(entry.getKey())) - { - //skip traversal of subtree and remove from the traversal iterator - return true; - } - return false; - } + /** + * if the full path to the entry is not contained in any of the paths to retain - remove it from + * the object this step does not remove entries whose full path is contained in a path to retain + * but are not equal to an entry to retain + * + * @param pathToEntry TODO + * @param entry TODO + * @return TODO + */ + protected boolean discardPath(String pathToEntry, Entry entry) { + if (!foundAsPrefix(pathToEntry) || !delim.accept(entry.getKey())) { + // skip traversal of subtree and remove from the traversal iterator + return true; + } + return false; + } - /** - * @param path TODO - * @return TODO - */ - protected boolean foundAsPrefix(String path) - { - for (String p : pathsToRetain) { - if (p == path || (p != null && path != null && p.startsWith(path))) { - return true; - } - } - return false; - } + /** + * @param path TODO + * @return TODO + */ + protected boolean foundAsPrefix(String path) { + for (String p : pathsToRetain) { + if (p == path || (p != null && path != null && p.startsWith(path))) { + return true; + } + } + return false; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverseAction.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverseAction.java index d2e2bb8..2aee21c 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverseAction.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverseAction.java @@ -5,83 +5,84 @@ import java.util.Map.Entry; /** - * An interface for a processing action on the nodes of a {@link M} tree - * while traversing it. The order in which the callbacks are listed - * below is the order in which they are called by the {@link TreeTraverser} - *

- * See package-info for more details + * An interface for a processing action on the nodes of a {@link M} tree while traversing it. The + * order in which the callbacks are listed below is the order in which they are called by the {@link + * TreeTraverser} + * + *

See package-info for more details * * @author adoneitan@gmail.com */ public interface TreeTraverseAction, L extends List> { - /** - * called before any traversal of the {@link M} tree starts - * @param object TODO - * @return true if traversal should start at all - */ - boolean start(M object); + /** + * called before any traversal of the {@link M} tree starts + * + * @param object TODO + * @return true if traversal should start at all + */ + boolean start(M object); - /** - * called when a new entry is encountered and before any processing is performed on it - * @param fullPathToEntry TODO - * @param entry TODO - * @return true if the entry should be processed - */ - boolean traverseEntry(String fullPathToEntry, Entry entry); + /** + * called when a new entry is encountered and before any processing is performed on it + * + * @param fullPathToEntry TODO + * @param entry TODO + * @return true if the entry should be processed + */ + boolean traverseEntry(String fullPathToEntry, Entry entry); - /** - * the last callback for each entry in an {@link M} map. if this method returns true - * the {@link TreeTraverser} removes the entry from the map. there is no further - * handling of the entry. - * - * @param fullPathToEntry TODO - * @param entry TODO - * @return true if the entry and its subtree should be removed from the M tree - */ - boolean removeEntry(String fullPathToEntry, Entry entry); + /** + * the last callback for each entry in an {@link M} map. if this method returns true the {@link + * TreeTraverser} removes the entry from the map. there is no further handling of the entry. + * + * @param fullPathToEntry TODO + * @param entry TODO + * @return true if the entry and its subtree should be removed from the M tree + */ + boolean removeEntry(String fullPathToEntry, Entry entry); - /** - * called when a non-leaf entry is encountered inside an M object - * - * @param fullPathToSubtree TODO - * @param entryValue TODO - * @return true if the non-leaf entry should be recursively traversed - */ - boolean recurInto(String fullPathToSubtree, M entryValue); + /** + * called when a non-leaf entry is encountered inside an M object + * + * @param fullPathToSubtree TODO + * @param entryValue TODO + * @return true if the non-leaf entry should be recursively traversed + */ + boolean recurInto(String fullPathToSubtree, M entryValue); - /** - * called when a non-leaf item is encountered inside an L object - * @param fullPathToContainingList TODO - * @param entryValue TODO - * @return true if the non-leaf item should be recursively traversed - */ - boolean recurInto(String fullPathToContainingList, L entryValue); + /** + * called when a non-leaf item is encountered inside an L object + * + * @param fullPathToContainingList TODO + * @param entryValue TODO + * @return true if the non-leaf item should be recursively traversed + */ + boolean recurInto(String fullPathToContainingList, L entryValue); - /** - * called for each leaf of an M map is encountered - * @param fullPathToEntry TODO - * @param entry TODO - */ - void handleLeaf(String fullPathToEntry, Entry entry); + /** + * called for each leaf of an M map is encountered + * + * @param fullPathToEntry TODO + * @param entry TODO + */ + void handleLeaf(String fullPathToEntry, Entry entry); - /** - * called for each leaf of an L list is encountered - * @param fullPathToContainingList - the item - * @param listIndex - the ordered location of the item in the list - * @param listItem - - */ - void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem); + /** + * called for each leaf of an L list is encountered + * + * @param fullPathToContainingList - the item + * @param listIndex - the ordered location of the item in the list + * @param listItem - + */ + void handleLeaf(String fullPathToContainingList, int listIndex, Object listItem); - /** - * called after the traversal ends, - * and just before the {@link #start} method exits - */ - void end(); + /** called after the traversal ends, and just before the {@link #start} method exits */ + void end(); - /** - * holds the result of the traversal, - * as assigned by the action implementing this interface - * @return result - */ - Object result(); + /** + * holds the result of the traversal, as assigned by the action implementing this interface + * + * @return result + */ + Object result(); } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverser.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverser.java index f410d6f..6ad703f 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverser.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/TreeTraverser.java @@ -1,92 +1,89 @@ package net.minidev.json.actions.traverse; -import net.minidev.json.actions.path.PathDelimiter; - import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import net.minidev.json.actions.path.PathDelimiter; /** * Traverses every node of a tree made up of a combination of {@link Map}s and {@link List}s - *

- * {@link TreeTraverser} accepts an action and provides callback hooks for it to act - * on the traversed nodes at each significant step. See {@link TreeTraverseAction}. - *

- * See package-info for more details * - * @author adoneitan@gmail.com + *

{@link TreeTraverser} accepts an action and provides callback hooks for it to act on the + * traversed nodes at each significant step. See {@link TreeTraverseAction}. * + *

See package-info for more details + * + * @author adoneitan@gmail.com */ public class TreeTraverser, L extends List> { - protected TreeTraverseAction action; - protected PathDelimiter delim; - protected String pathPrefix = ""; - - public TreeTraverser(TreeTraverseAction action, PathDelimiter delim) { - this.action = action; - this.delim = delim; - } + protected TreeTraverseAction action; + protected PathDelimiter delim; + protected String pathPrefix = ""; - public TreeTraverser with(String pathPrefix) { - this.pathPrefix = pathPrefix; - return this; - } + public TreeTraverser(TreeTraverseAction action, PathDelimiter delim) { + this.action = action; + this.delim = delim; + } - public void traverse(M map) { - if (action.start(map)) { - depthFirst(pathPrefix, map); - } - action.end(); - } + public TreeTraverser with(String pathPrefix) { + this.pathPrefix = pathPrefix; + return this; + } - @SuppressWarnings("unchecked") - private void depthFirst(String fullPath, M map) { - if (map == null || map.entrySet() == null || !action.recurInto(fullPath, map)) { - return; - } - Iterator> it = map.entrySet().iterator(); - while (it.hasNext()) { - Entry entry = it.next(); - String fullPathToEntry = buildPath(fullPath, entry.getKey()); + public void traverse(M map) { + if (action.start(map)) { + depthFirst(pathPrefix, map); + } + action.end(); + } - if (!action.traverseEntry(fullPathToEntry, entry)) { - continue; - } else if (action.removeEntry(fullPathToEntry, entry)) { - it.remove(); - continue; - } + @SuppressWarnings("unchecked") + private void depthFirst(String fullPath, M map) { + if (map == null || map.entrySet() == null || !action.recurInto(fullPath, map)) { + return; + } + Iterator> it = map.entrySet().iterator(); + while (it.hasNext()) { + Entry entry = it.next(); + String fullPathToEntry = buildPath(fullPath, entry.getKey()); - if (entry.getValue() instanceof Map) { - depthFirst(fullPathToEntry, (M) entry.getValue()); - } else if (entry.getValue() instanceof List) { - depthFirst(fullPathToEntry, (L) entry.getValue()); - } else { - action.handleLeaf(fullPathToEntry, entry); - } - } - } + if (!action.traverseEntry(fullPathToEntry, entry)) { + continue; + } else if (action.removeEntry(fullPathToEntry, entry)) { + it.remove(); + continue; + } - @SuppressWarnings("unchecked") - private void depthFirst(String fullPath, L list) { - if (!action.recurInto(fullPath, (L) list)) { - return; - } - int listIndex = 0; - for (Object listItem : list.toArray()) { - if (listItem instanceof Map) { - depthFirst(fullPath, (M) listItem); - } else if (listItem instanceof List) { - depthFirst(fullPath, (L) listItem); - } else { - action.handleLeaf(fullPath, listIndex, listItem); - } - listIndex++; - } - } + if (entry.getValue() instanceof Map) { + depthFirst(fullPathToEntry, (M) entry.getValue()); + } else if (entry.getValue() instanceof List) { + depthFirst(fullPathToEntry, (L) entry.getValue()); + } else { + action.handleLeaf(fullPathToEntry, entry); + } + } + } - private String buildPath(String fullPath, String entryKey) { - return pathPrefix.equals(fullPath) ? pathPrefix + entryKey : fullPath + delim.str() + entryKey; - } + @SuppressWarnings("unchecked") + private void depthFirst(String fullPath, L list) { + if (!action.recurInto(fullPath, (L) list)) { + return; + } + int listIndex = 0; + for (Object listItem : list.toArray()) { + if (listItem instanceof Map) { + depthFirst(fullPath, (M) listItem); + } else if (listItem instanceof List) { + depthFirst(fullPath, (L) listItem); + } else { + action.handleLeaf(fullPath, listIndex, listItem); + } + listIndex++; + } + } + private String buildPath(String fullPath, String entryKey) { + return pathPrefix.equals(fullPath) ? pathPrefix + entryKey : fullPath + delim.str() + entryKey; + } } diff --git a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/package-info.java b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/package-info.java index d6c549b..a62a3ac 100644 --- a/json-smart-action/src/main/java/net/minidev/json/actions/traverse/package-info.java +++ b/json-smart-action/src/main/java/net/minidev/json/actions/traverse/package-info.java @@ -1,23 +1,23 @@ /** - * * Traverse all the nodes in a {@link net.minidev.json.JSONObject} and process them - *

- * The traversal starts at the root and moves breadth-first down the branches. - * The {@link net.minidev.json.actions.traverse.TreeTraverser} accepts a - * {@link net.minidev.json.actions.traverse.JSONTraverseAction} and provides callback hooks at each significant - * step which the {@link net.minidev.json.actions.traverse.JSONTraverseAction} may use to process - * the nodes. - *

- * The {@link net.minidev.json.actions.traverse.TreeTraverser} assumes that paths in the tree which the - * {@link net.minidev.json.JSONObject} represents are specified in the n-gram format - a list of keys from the - * root down separated by dots: - *

- * K0[[[[.K1].K2].K3]...] - *

- * A key to the right of a dot is a direct child of a key to the left of a dot. - * Keys with a dot in their name are not supported. - *

- * Sample usage: + * + *

The traversal starts at the root and moves breadth-first down the branches. The {@link + * net.minidev.json.actions.traverse.TreeTraverser} accepts a {@link + * net.minidev.json.actions.traverse.JSONTraverseAction} and provides callback hooks at each + * significant step which the {@link net.minidev.json.actions.traverse.JSONTraverseAction} may use + * to process the nodes. + * + *

The {@link net.minidev.json.actions.traverse.TreeTraverser} assumes that paths in the tree + * which the {@link net.minidev.json.JSONObject} represents are specified in the n-gram format - a + * list of keys from the root down separated by dots: + * + *

K0[[[[.K1].K2].K3]...] + * + *

A key to the right of a dot is a direct child of a key to the left of a dot. Keys with a dot + * in their name are not supported. + * + *

Sample usage: + * *

  * TraverseAction tAction = new TraverseAction(){...};
  * JSONTraverser jsonTrv = new JSONTraverser(tAction);
@@ -27,4 +27,4 @@
  *
  * @author adoneitan@gmail.com
  */
-package net.minidev.json.actions.traverse;
\ No newline at end of file
+package net.minidev.json.actions.traverse;
diff --git a/json-smart-action/src/test/java/net/minidev/json/test/actions/ElementRemoverTest.java b/json-smart-action/src/test/java/net/minidev/json/test/actions/ElementRemoverTest.java
index 1e9451f..e4f956a 100644
--- a/json-smart-action/src/test/java/net/minidev/json/test/actions/ElementRemoverTest.java
+++ b/json-smart-action/src/test/java/net/minidev/json/test/actions/ElementRemoverTest.java
@@ -1,18 +1,16 @@
 package net.minidev.json.test.actions;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.stream.Stream;
 import net.minidev.json.JSONObject;
 import net.minidev.json.JSONValue;
 import net.minidev.json.actions.ElementRemover;
 import net.minidev.json.parser.ParseException;
-
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
-import java.util.stream.Stream;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
 /**
  * Tests {@link ElementRemover}
  *
@@ -21,39 +19,61 @@
 // @RunWith(Parameterized.class)
 public class ElementRemoverTest {
 
-	public ElementRemoverTest() {
-	}
-
-	private static String filter(String test) {
-		if (test == null)
-			return null;
-		return test.replace("'", "\"");
-	}
-	
-	public static Stream params() {
-		return Stream.of(
-				Arguments.of("{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}", null,                     "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}"),
-				Arguments.of("{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}", "{}",                     "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}"),
-				Arguments.of("{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}", "{'k0':'v2'}",            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}"),
-				Arguments.of("{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}", "{'k2':'v2'}",            "{'k0':{},'k1':{'k3':'v3'}}"),
-				Arguments.of("{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}", "{'k0':{'k2':'v2'}}",     "{'k1':{'k2':'v2','k3':'v3'}}"),
-				Arguments.of("{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}", "{'k2':'v2','k3':'v3'}",  "{'k0':{},'k1':{}}"),
-				Arguments.of("{'k0':{}}",                                     "{}",                     "{'k0':{}}")
-				);
-			};
-
-	@ParameterizedTest
-	@MethodSource("params")
-	public void test(String jsonToClean, String elementsToRemove, String expectedJson) throws ParseException {
-		jsonToClean = filter(jsonToClean);
-		elementsToRemove = filter(elementsToRemove);
-		expectedJson = filter(expectedJson);
-		
-		JSONObject objectToClean = jsonToClean != null ? (JSONObject) JSONValue.parseWithException(jsonToClean) : null;
-		JSONObject expectedObject = expectedJson != null ? (JSONObject) JSONValue.parseWithException(expectedJson) : null;
-		JSONObject toRemove = elementsToRemove != null ? (JSONObject) JSONValue.parseWithException(elementsToRemove) : null;
-		ElementRemover er = new ElementRemover(toRemove);
-		er.remove(objectToClean);
-		assertEquals(expectedObject, objectToClean);
-	}
+  public ElementRemoverTest() {}
+
+  private static String filter(String test) {
+    if (test == null) return null;
+    return test.replace("'", "\"");
+  }
+
+  public static Stream params() {
+    return Stream.of(
+        Arguments.of(
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}",
+            null,
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}"),
+        Arguments.of(
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}",
+            "{}",
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}"),
+        Arguments.of(
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}",
+            "{'k0':'v2'}",
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}"),
+        Arguments.of(
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}",
+            "{'k2':'v2'}",
+            "{'k0':{},'k1':{'k3':'v3'}}"),
+        Arguments.of(
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}",
+            "{'k0':{'k2':'v2'}}",
+            "{'k1':{'k2':'v2','k3':'v3'}}"),
+        Arguments.of(
+            "{'k0':{'k2':'v2'},'k1':{'k2':'v2','k3':'v3'}}",
+            "{'k2':'v2','k3':'v3'}",
+            "{'k0':{},'k1':{}}"),
+        Arguments.of("{'k0':{}}", "{}", "{'k0':{}}"));
+  }
+  ;
+
+  @ParameterizedTest
+  @MethodSource("params")
+  public void test(String jsonToClean, String elementsToRemove, String expectedJson)
+      throws ParseException {
+    jsonToClean = filter(jsonToClean);
+    elementsToRemove = filter(elementsToRemove);
+    expectedJson = filter(expectedJson);
+
+    JSONObject objectToClean =
+        jsonToClean != null ? (JSONObject) JSONValue.parseWithException(jsonToClean) : null;
+    JSONObject expectedObject =
+        expectedJson != null ? (JSONObject) JSONValue.parseWithException(expectedJson) : null;
+    JSONObject toRemove =
+        elementsToRemove != null
+            ? (JSONObject) JSONValue.parseWithException(elementsToRemove)
+            : null;
+    ElementRemover er = new ElementRemover(toRemove);
+    er.remove(objectToClean);
+    assertEquals(expectedObject, objectToClean);
+  }
 }
diff --git a/json-smart-action/src/test/java/net/minidev/json/test/actions/KeysPrintActionTest.java b/json-smart-action/src/test/java/net/minidev/json/test/actions/KeysPrintActionTest.java
index b04b4d2..3c21606 100644
--- a/json-smart-action/src/test/java/net/minidev/json/test/actions/KeysPrintActionTest.java
+++ b/json-smart-action/src/test/java/net/minidev/json/test/actions/KeysPrintActionTest.java
@@ -1,44 +1,44 @@
 package net.minidev.json.test.actions;
 
-import org.junit.jupiter.api.Test;
-
 import net.minidev.json.JSONObject;
 import net.minidev.json.JSONValue;
 import net.minidev.json.actions.traverse.JSONTraverser;
 import net.minidev.json.actions.traverse.KeysPrintAction;
 import net.minidev.json.parser.ParseException;
+import org.junit.jupiter.api.Test;
 
 /**
  * @author adoneitan@gmail.com
  * @since 30 May 2016
  */
 public class KeysPrintActionTest {
-	@Test
-	public void test() throws ParseException {
-		KeysPrintAction p = new KeysPrintAction();
-		JSONTraverser t = new JSONTraverser(p);
-		
-		String data ="{" +
-				"'k0':{" +
-				"'k01':{" +
-					"'k011':'v2'" +
-				"}" +
-			"}," +
-			"'k1':{" +
-				"'k11':{" +
-					"'k111':'v5'" +
-				"}," +
-				"'k12':{" +
-					"'k121':'v5'" +
-				"}" +
-			"}," +
-			"'k3':{" +
-				"'k31':{" +
-					"'k311':'v5'" +
-				"}" +
-			"}" +
-		"}";
-		JSONObject jo = (JSONObject) JSONValue.parseWithException(data.replace("'", "\""));
-		t.traverse(jo);
-	}
-}
\ No newline at end of file
+  @Test
+  public void test() throws ParseException {
+    KeysPrintAction p = new KeysPrintAction();
+    JSONTraverser t = new JSONTraverser(p);
+
+    String data =
+        "{"
+            + "'k0':{"
+            + "'k01':{"
+            + "'k011':'v2'"
+            + "}"
+            + "},"
+            + "'k1':{"
+            + "'k11':{"
+            + "'k111':'v5'"
+            + "},"
+            + "'k12':{"
+            + "'k121':'v5'"
+            + "}"
+            + "},"
+            + "'k3':{"
+            + "'k31':{"
+            + "'k311':'v5'"
+            + "}"
+            + "}"
+            + "}";
+    JSONObject jo = (JSONObject) JSONValue.parseWithException(data.replace("'", "\""));
+    t.traverse(jo);
+  }
+}
diff --git a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathLocatorTest.java b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathLocatorTest.java
index 99a02f5..25afb1b 100644
--- a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathLocatorTest.java
+++ b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathLocatorTest.java
@@ -1,18 +1,16 @@
 package net.minidev.json.test.actions;
 
-import net.minidev.json.actions.PathLocator;
-import net.minidev.json.JSONArray;
-import net.minidev.json.JSONObject;
-import net.minidev.json.JSONValue;
-import net.minidev.json.parser.ParseException;
-
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Stream;
-
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+import net.minidev.json.JSONValue;
+import net.minidev.json.actions.PathLocator;
+import net.minidev.json.parser.ParseException;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -23,102 +21,140 @@
 // @ExtendWith(Parameterized.class)
 public class PathLocatorTest {
 
-	public static Stream params() {
-		 return Stream.of(
-				//nulls, bad/empty keys
-				Arguments.of(null,                                                  null,                           new String[]{}                       ),
-				Arguments.of(null,                                                  "",                             new String[]{}                       ),
-				Arguments.of(null,                                                  "k1",                           new String[]{}                       ),
-				Arguments.of(null,                                                  new String[]{},                 new String[]{}                       ),
-				Arguments.of(null,                                                  new JSONArray(),                new String[]{}                       ),
-				Arguments.of(null,                                                  new ArrayList(0),       new String[]{}                       ),//5
-				//empty json, bad/empty keys
-				Arguments.of("{}",                                                  null,                           new String[]{}                       ),
-				Arguments.of("{}",                                                  "",                             new String[]{}                       ),
-				Arguments.of("{}",                                                  "k1",                           new String[]{}                       ),
-				Arguments.of("{}",                                                  new String[]{},                 new String[]{}                       ),
-				Arguments.of("{}",                                                  new JSONArray(),                new String[]{}                       ),//10
-				Arguments.of("{}",                                                  new ArrayList(0),       new String[]{}                       ),
-				//simple json, bad/empty keys
-				Arguments.of("{\"k0\":\"v0\"}",                                     null,                           new String[]{}                       ),
-				Arguments.of("{\"k0\":\"v0\"}",                                     "",                             new String[]{}                       ),
-				Arguments.of("{\"k0\":\"v0\"}",                                     "k1",                           new String[]{}                       ),
-				Arguments.of("{\"k0\":\"v0\"}",                                     new String[]{},                 new String[]{}                       ),//15
-				Arguments.of("{\"k0\":\"v0\"}",                                     new JSONArray(),                new String[]{}                       ),
-				Arguments.of("{\"k0\":\"v0\"}",                                     new ArrayList(0),       new String[]{}                       ),
-				//simple json, valid/invalid keys
-				Arguments.of("{\"k0\":\"v0\"}",                                     "k0",                           new String[]{"k0"}                   ),
-				Arguments.of("{\"k0\":\"v0\"}",                                     "v0",                           new String[]{}                       ),
-				Arguments.of("{\"k0\":\"v0\"}",                                     "k0.k1",                        new String[]{}                       ),//20
-				Arguments.of("{\"k0\":\"v0\"}",                                     "k1.k0",                        new String[]{}                       ),
-				Arguments.of("{\"k0\":null}",                                       "k0",                           new String[]{"k0"}                   ),
-				Arguments.of("{\"k0\":null}",                                       null,                           new String[]{}                       ),
-				//key with dot char
-				Arguments.of("{\"k0.k1\":\"v0\"}",                                  "k0",                           new String[]{}                       ),
-				Arguments.of("{\"k0.k1\":\"v0\"}",                                  "k1",                           new String[]{}                       ),//25
-				Arguments.of("{\"k0.k1\":\"v0\"}",                                  "k0.k1",                        new String[]{}                       ),
-				// key with dot ambiguity
-				Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}",        "k0",                           new String[]{"k0"}                   ),
-				Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}",        "k1",                           new String[]{}                       ),
-				Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}",        "k0.k1",                        new String[]{"k0.k1"}                ),
-				Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",   "k0.k1",                        new String[]{"k0.k1"}                ),//30
-				Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",   "k0.k1.k2",                     new String[]{"k0.k1.k2"}             ),
-				Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",   "k1.k2",                        new String[]{}                       ),
-				Arguments.of("{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}","k0",                           new String[]{"k0"}                   ),
-				Arguments.of("{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}","k1.k2",                        new String[]{"k1.k2"}                ),
-				//ignore non-existent keys but keep good keys
-				Arguments.of("{\"k0\":\"v0\",\"k1\":\"v1\"}",                      new String[]{"k0","k2"},         new String[]{"k0"}                   ),//35
-				Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k2"},         new String[]{"k0"}                   ),
-				Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1.k2"},      new String[]{"k0", "k1.k2"}          ),
-				Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1.k2.k3"},   new String[]{"k0"}                   ),
-				Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1.k2","k1"}, new String[]{"k0","k1","k1.k2"}      ),
-				Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1","k0.k2"}, new String[]{"k0","k1"}              ),//40
-				Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1","k2"},    new String[]{"k0","k1"}              ),
-				Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k1.k2"},           new String[]{"k1.k2"}                ),
-				//arrays - key inside array treated as child
-				Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",           "k0",                           new String[]{"k0"}                   ),
-				Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",           "k0.k1",                        new String[]{"k0.k1"}                ),
-				Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",           "k0.k1.k2",                     new String[]{"k0.k1.k2"}             ),//45
-				Arguments.of("{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}", "k0.k1.k2",                     new String[]{"k0.k1.k2", "k0.k1.k2"} )
-		);
-	}
+  public static Stream params() {
+    return Stream.of(
+        // nulls, bad/empty keys
+        Arguments.of(null, null, new String[] {}),
+        Arguments.of(null, "", new String[] {}),
+        Arguments.of(null, "k1", new String[] {}),
+        Arguments.of(null, new String[] {}, new String[] {}),
+        Arguments.of(null, new JSONArray(), new String[] {}),
+        Arguments.of(null, new ArrayList(0), new String[] {}), // 5
+        // empty json, bad/empty keys
+        Arguments.of("{}", null, new String[] {}),
+        Arguments.of("{}", "", new String[] {}),
+        Arguments.of("{}", "k1", new String[] {}),
+        Arguments.of("{}", new String[] {}, new String[] {}),
+        Arguments.of("{}", new JSONArray(), new String[] {}), // 10
+        Arguments.of("{}", new ArrayList(0), new String[] {}),
+        // simple json, bad/empty keys
+        Arguments.of("{\"k0\":\"v0\"}", null, new String[] {}),
+        Arguments.of("{\"k0\":\"v0\"}", "", new String[] {}),
+        Arguments.of("{\"k0\":\"v0\"}", "k1", new String[] {}),
+        Arguments.of("{\"k0\":\"v0\"}", new String[] {}, new String[] {}), // 15
+        Arguments.of("{\"k0\":\"v0\"}", new JSONArray(), new String[] {}),
+        Arguments.of("{\"k0\":\"v0\"}", new ArrayList(0), new String[] {}),
+        // simple json, valid/invalid keys
+        Arguments.of("{\"k0\":\"v0\"}", "k0", new String[] {"k0"}),
+        Arguments.of("{\"k0\":\"v0\"}", "v0", new String[] {}),
+        Arguments.of("{\"k0\":\"v0\"}", "k0.k1", new String[] {}), // 20
+        Arguments.of("{\"k0\":\"v0\"}", "k1.k0", new String[] {}),
+        Arguments.of("{\"k0\":null}", "k0", new String[] {"k0"}),
+        Arguments.of("{\"k0\":null}", null, new String[] {}),
+        // key with dot char
+        Arguments.of("{\"k0.k1\":\"v0\"}", "k0", new String[] {}),
+        Arguments.of("{\"k0.k1\":\"v0\"}", "k1", new String[] {}), // 25
+        Arguments.of("{\"k0.k1\":\"v0\"}", "k0.k1", new String[] {}),
+        // key with dot ambiguity
+        Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}", "k0", new String[] {"k0"}),
+        Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}", "k1", new String[] {}),
+        Arguments.of(
+            "{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}", "k0.k1", new String[] {"k0.k1"}),
+        Arguments.of(
+            "{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",
+            "k0.k1",
+            new String[] {"k0.k1"}), // 30
+        Arguments.of(
+            "{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",
+            "k0.k1.k2",
+            new String[] {"k0.k1.k2"}),
+        Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}", "k1.k2", new String[] {}),
+        Arguments.of(
+            "{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}", "k0", new String[] {"k0"}),
+        Arguments.of(
+            "{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}",
+            "k1.k2",
+            new String[] {"k1.k2"}),
+        // ignore non-existent keys but keep good keys
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":\"v1\"}", new String[] {"k0", "k2"}, new String[] {"k0"}), // 35
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k2"},
+            new String[] {"k0"}),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1.k2"},
+            new String[] {"k0", "k1.k2"}),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1.k2.k3"},
+            new String[] {"k0"}),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1.k2", "k1"},
+            new String[] {"k0", "k1", "k1.k2"}),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1", "k0.k2"},
+            new String[] {"k0", "k1"}), // 40
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1", "k2"},
+            new String[] {"k0", "k1"}),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k1.k2"},
+            new String[] {"k1.k2"}),
+        // arrays - key inside array treated as child
+        Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}", "k0", new String[] {"k0"}),
+        Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}", "k0.k1", new String[] {"k0.k1"}),
+        Arguments.of(
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",
+            "k0.k1.k2",
+            new String[] {"k0.k1.k2"}), // 45
+        Arguments.of(
+            "{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}",
+            "k0.k1.k2",
+            new String[] {"k0.k1.k2", "k0.k1.k2"}));
+  }
 
-	@ParameterizedTest
-	@MethodSource("params")
-	public void test(String jsonToSearch, Object keysToFind, String[] expectedFound) throws ParseException
-	{
-		JSONObject objectToSearch = jsonToSearch != null ? (JSONObject) JSONValue.parseWithException(jsonToSearch) : null;
-		PathLocator locator = switchKeyToRemove(keysToFind);
-		List found = locator.locate(objectToSearch);
-		assertEquals(Arrays.asList(expectedFound), found);
-	}
+  @ParameterizedTest
+  @MethodSource("params")
+  public void test(String jsonToSearch, Object keysToFind, String[] expectedFound)
+      throws ParseException {
+    JSONObject objectToSearch =
+        jsonToSearch != null ? (JSONObject) JSONValue.parseWithException(jsonToSearch) : null;
+    PathLocator locator = switchKeyToRemove(keysToFind);
+    List found = locator.locate(objectToSearch);
+    assertEquals(Arrays.asList(expectedFound), found);
+  }
 
-	@SuppressWarnings("unchecked")
-	private PathLocator switchKeyToRemove(Object keysToFind)
-	{
-		long m = System.currentTimeMillis();
-		if (keysToFind == null && m % 4 == 0) {
-			// System.out.println("cast to String");
-			return new PathLocator((String)null);
-		} else if (keysToFind == null && m % 4 == 1) {
-			// System.out.println("cast to String[]");
-			return new PathLocator((String[])null);
-		} else if (keysToFind == null && m % 4 == 2) {
-			// System.out.println("cast to JSONArray");
-			return new PathLocator((JSONArray)null);
-		} else if (keysToFind == null && m % 4 == 3) {
-			// System.out.println("cast to List");
-			return new PathLocator((List)null);
-		} else if (keysToFind instanceof String) {
-			return new PathLocator((String) keysToFind);
-		} else if (keysToFind instanceof String[]) {
-			return new PathLocator((String[]) keysToFind);
-		} else if (keysToFind instanceof JSONArray) {
-			return new PathLocator((JSONArray) keysToFind);
-		} else if (keysToFind instanceof List) {
-			return new PathLocator((List) keysToFind);
-		} else {
-			throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
-		}
-	}
-}
\ No newline at end of file
+  @SuppressWarnings("unchecked")
+  private PathLocator switchKeyToRemove(Object keysToFind) {
+    long m = System.currentTimeMillis();
+    if (keysToFind == null && m % 4 == 0) {
+      // System.out.println("cast to String");
+      return new PathLocator((String) null);
+    } else if (keysToFind == null && m % 4 == 1) {
+      // System.out.println("cast to String[]");
+      return new PathLocator((String[]) null);
+    } else if (keysToFind == null && m % 4 == 2) {
+      // System.out.println("cast to JSONArray");
+      return new PathLocator((JSONArray) null);
+    } else if (keysToFind == null && m % 4 == 3) {
+      // System.out.println("cast to List");
+      return new PathLocator((List) null);
+    } else if (keysToFind instanceof String) {
+      return new PathLocator((String) keysToFind);
+    } else if (keysToFind instanceof String[]) {
+      return new PathLocator((String[]) keysToFind);
+    } else if (keysToFind instanceof JSONArray) {
+      return new PathLocator((JSONArray) keysToFind);
+    } else if (keysToFind instanceof List) {
+      return new PathLocator((List) keysToFind);
+    } else {
+      throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
+    }
+  }
+}
diff --git a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathRemoverTest.java b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathRemoverTest.java
index c7b433e..9a4358e 100644
--- a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathRemoverTest.java
+++ b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathRemoverTest.java
@@ -1,18 +1,16 @@
 package net.minidev.json.test.actions;
 
-import net.minidev.json.actions.PathRemover;
-import net.minidev.json.JSONArray;
-import net.minidev.json.JSONObject;
-import net.minidev.json.JSONValue;
-import net.minidev.json.parser.ParseException;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Stream;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+import net.minidev.json.JSONValue;
+import net.minidev.json.actions.PathRemover;
+import net.minidev.json.parser.ParseException;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -24,81 +22,127 @@
  */
 // @RunWith(Parameterized.class)
 public class PathRemoverTest {
-	public static Stream params() {
-		 return Stream.of(
-				Arguments.of(null,                                                             "key",                    null                                             ), // null json
-				Arguments.of("{}",                                                             "key",                    "{}"                                             ), // empty json
-				Arguments.of("{\"first\": null}",                                              null,                     "{\"first\": null}"                              ), // null key
-				Arguments.of("{\"first\": null}",                                              "",                       "{\"first\": null}"                              ), // empty string key
-				Arguments.of("{\"first\": null}",                                              new String[]{},           "{\"first\": null}"                              ), // empty string array key
-				Arguments.of("{\"first\": null}",                                              new JSONArray(),          "{\"first\": null}"                              ), // empty json array key
-				Arguments.of("{\"first\": null}",                                              new ArrayList(0), "{\"first\": null}"                              ), // empty list key
-				Arguments.of("{\"first\": null}",                                              "first",                  "{}"                                             ), // remove root key
-				Arguments.of("{\"first.f1\": null}",                                           "first.f1",               "{}"                                             ), // key with dot
-				Arguments.of("{\"first.f1\": \"withDot\", \"first\":{\"f1\": null}}",          "first.f1",               "{\"first\":{}}"                                 ), //9 key with dot ambiguity
-				Arguments.of("{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}",                 "first.f2.f3.id",         "{\"first\":{\"f2\":{\"f3\":{}}}}"               ), // nested object remove single leaf
-				Arguments.of("{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}",                 "notfound",               "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}" ), // nested object key does not exist
-				Arguments.of("{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}", "first.f2.f3.id",         "{\"first\":{\"f2\":{\"f3\":{\"name\":\"me\"}}}}"), // nested object remove first leaf
-				Arguments.of("{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}", "first.f2.f3.name",       "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}" ), //13 nested object remove last leaf
-				Arguments.of("{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}", "first.f2.f3",            "{\"first\":{\"f2\":{}}}"                        ), // nested object remove intermediate node
-				Arguments.of("{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}", "first",                  "{}"                                             ), // nested object remove root
-				Arguments.of("{\"first\":{\"f2\":[[1,{\"id\":\"id1\"},3],4]}}",                "first.f2.id",            "{\"first\":{\"f2\":[[1,{},3],4]}}"              ), // double nested array remove leaf
-				Arguments.of("{\"first\":{\"f2\":[[1,{\"id\":\"id1\"},3],4]}}",                "first.f2",               "{\"first\":{}}"                                 ), // double nested array remove array
-				Arguments.of("{\"first\":[[1,{\"id\":\"id1\"},3],4]}",                         "first",                  "{}"                                             ), // double nested array remove root
-				//arrays
-				Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",                    "k0.k1",                    "{\"k0\":{}}"                                    ), // value is array
-				Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",                    "k0.k1.k2",                 "{\"k0\":{\"k1\":[1,{},3,4]}}"                   ), // full path into array object
-				Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",                    "k0.k1.3" ,                 "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}"      ), // full path into array primitive
-				Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},{\"k2\":\"v2\"},3,4]}}",    "k0.k1.k2",                 "{\"k0\":{\"k1\":[1,{},{},3,4]}}"                ), // full path into array with identical items
-				// composite json remove all roots
-				Arguments.of("{\"first\": {\"f2\":{\"id\":\"id1\"}}, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5, 6, {\"id\": 123}], \"third\": 789, \"id\": null}",
-						(JSONArray) JSONValue.parse("[\"first\",\"second\",\"third\",\"id\"]"),
-						"{}" ),
-				// composite json remove all leaves
-				Arguments.of("{\"first\": {\"f2\":{\"id\":\"id1\"}}, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5, 6, {\"id\": 123}], \"third\": 789, \"id\": null}",
-						(List) Arrays.asList("first.f2.id", "second.k1.id", "second.id", "third", "id"),
-						"{\"first\": {\"f2\":{}}, \"second\": [{\"k1\":{}}, 4, 5, 6, {}]}" )
-		);
-	}
-
-	@ParameterizedTest
-	@MethodSource("params")
-	public void test(String jsonToClean, Object keyToRemove, String expectedJson) throws ParseException
-	{
-		JSONObject objectToClean = jsonToClean != null ? (JSONObject) JSONValue.parseWithException(jsonToClean) : null;
-		JSONObject expectedObject = expectedJson != null ? (JSONObject) JSONValue.parseWithException(expectedJson): null;
-		PathRemover cl = switchKeyToRemove(keyToRemove);
-		cl.remove(objectToClean);
-		assertEquals(expectedObject, objectToClean);
-	}
+  public static Stream params() {
+    return Stream.of(
+        Arguments.of(null, "key", null), // null json
+        Arguments.of("{}", "key", "{}"), // empty json
+        Arguments.of("{\"first\": null}", null, "{\"first\": null}"), // null key
+        Arguments.of("{\"first\": null}", "", "{\"first\": null}"), // empty string key
+        Arguments.of(
+            "{\"first\": null}", new String[] {}, "{\"first\": null}"), // empty string array key
+        Arguments.of(
+            "{\"first\": null}", new JSONArray(), "{\"first\": null}"), // empty json array key
+        Arguments.of(
+            "{\"first\": null}", new ArrayList(0), "{\"first\": null}"), // empty list key
+        Arguments.of("{\"first\": null}", "first", "{}"), // remove root key
+        Arguments.of("{\"first.f1\": null}", "first.f1", "{}"), // key with dot
+        Arguments.of(
+            "{\"first.f1\": \"withDot\", \"first\":{\"f1\": null}}",
+            "first.f1",
+            "{\"first\":{}}"), // 9 key with dot ambiguity
+        Arguments.of(
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}",
+            "first.f2.f3.id",
+            "{\"first\":{\"f2\":{\"f3\":{}}}}"), // nested object remove single leaf
+        Arguments.of(
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}",
+            "notfound",
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}"), // nested object key does not exist
+        Arguments.of(
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}",
+            "first.f2.f3.id",
+            "{\"first\":{\"f2\":{\"f3\":{\"name\":\"me\"}}}}"), // nested object remove first leaf
+        Arguments.of(
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}",
+            "first.f2.f3.name",
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\"}}}}"), // 13 nested object remove last leaf
+        Arguments.of(
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}",
+            "first.f2.f3",
+            "{\"first\":{\"f2\":{}}}"), // nested object remove intermediate node
+        Arguments.of(
+            "{\"first\":{\"f2\":{\"f3\":{\"id\":\"id1\",\"name\":\"me\"}}}}",
+            "first",
+            "{}"), // nested object remove root
+        Arguments.of(
+            "{\"first\":{\"f2\":[[1,{\"id\":\"id1\"},3],4]}}",
+            "first.f2.id",
+            "{\"first\":{\"f2\":[[1,{},3],4]}}"), // double nested array remove leaf
+        Arguments.of(
+            "{\"first\":{\"f2\":[[1,{\"id\":\"id1\"},3],4]}}",
+            "first.f2",
+            "{\"first\":{}}"), // double nested array remove array
+        Arguments.of(
+            "{\"first\":[[1,{\"id\":\"id1\"},3],4]}",
+            "first",
+            "{}"), // double nested array remove root
+        // arrays
+        Arguments.of(
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}", "k0.k1", "{\"k0\":{}}"), // value is array
+        Arguments.of(
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",
+            "k0.k1.k2",
+            "{\"k0\":{\"k1\":[1,{},3,4]}}"), // full path into array object
+        Arguments.of(
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",
+            "k0.k1.3",
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}"), // full path into array primitive
+        Arguments.of(
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},{\"k2\":\"v2\"},3,4]}}",
+            "k0.k1.k2",
+            "{\"k0\":{\"k1\":[1,{},{},3,4]}}"), // full path into array with identical items
+        // composite json remove all roots
+        Arguments.of(
+            "{\"first\": {\"f2\":{\"id\":\"id1\"}}, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5,"
+                + " 6, {\"id\": 123}], \"third\": 789, \"id\": null}",
+            (JSONArray) JSONValue.parse("[\"first\",\"second\",\"third\",\"id\"]"),
+            "{}"),
+        // composite json remove all leaves
+        Arguments.of(
+            "{\"first\": {\"f2\":{\"id\":\"id1\"}}, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5,"
+                + " 6, {\"id\": 123}], \"third\": 789, \"id\": null}",
+            (List) Arrays.asList("first.f2.id", "second.k1.id", "second.id", "third", "id"),
+            "{\"first\": {\"f2\":{}}, \"second\": [{\"k1\":{}}, 4, 5, 6, {}]}"));
+  }
 
-	@SuppressWarnings("unchecked")
-	private PathRemover switchKeyToRemove(Object keyToRemove)
-	{
-		long m = System.currentTimeMillis();
-		if (keyToRemove == null && m % 4 == 0) {
-			// System.out.println("cast to String");
-			return new PathRemover((String)null);
-		} else if (keyToRemove == null && m % 4 == 1) {
-			// System.out.println("cast to String[]");
-			return new PathRemover((String[])null);
-		} else if (keyToRemove == null && m % 4 == 2) {
-			// System.out.println("cast to JSONArray");
-			return new PathRemover((JSONArray)null);
-		} else if (keyToRemove == null && m % 4 == 3) {
-			// System.out.println("cast to List");
-			return new PathRemover((List)null);
-		} else if (keyToRemove instanceof String) {
-			return new PathRemover((String)keyToRemove);
-		} else if (keyToRemove instanceof String[]) {
-			return new PathRemover((String[])keyToRemove);
-		} else if (keyToRemove instanceof JSONArray) {
-			return new PathRemover((JSONArray)keyToRemove);
-		} else if (keyToRemove instanceof List) {
-			return new PathRemover((List)keyToRemove);
-		} else {
-			throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
-		}
-	}
+  @ParameterizedTest
+  @MethodSource("params")
+  public void test(String jsonToClean, Object keyToRemove, String expectedJson)
+      throws ParseException {
+    JSONObject objectToClean =
+        jsonToClean != null ? (JSONObject) JSONValue.parseWithException(jsonToClean) : null;
+    JSONObject expectedObject =
+        expectedJson != null ? (JSONObject) JSONValue.parseWithException(expectedJson) : null;
+    PathRemover cl = switchKeyToRemove(keyToRemove);
+    cl.remove(objectToClean);
+    assertEquals(expectedObject, objectToClean);
+  }
 
+  @SuppressWarnings("unchecked")
+  private PathRemover switchKeyToRemove(Object keyToRemove) {
+    long m = System.currentTimeMillis();
+    if (keyToRemove == null && m % 4 == 0) {
+      // System.out.println("cast to String");
+      return new PathRemover((String) null);
+    } else if (keyToRemove == null && m % 4 == 1) {
+      // System.out.println("cast to String[]");
+      return new PathRemover((String[]) null);
+    } else if (keyToRemove == null && m % 4 == 2) {
+      // System.out.println("cast to JSONArray");
+      return new PathRemover((JSONArray) null);
+    } else if (keyToRemove == null && m % 4 == 3) {
+      // System.out.println("cast to List");
+      return new PathRemover((List) null);
+    } else if (keyToRemove instanceof String) {
+      return new PathRemover((String) keyToRemove);
+    } else if (keyToRemove instanceof String[]) {
+      return new PathRemover((String[]) keyToRemove);
+    } else if (keyToRemove instanceof JSONArray) {
+      return new PathRemover((JSONArray) keyToRemove);
+    } else if (keyToRemove instanceof List) {
+      return new PathRemover((List) keyToRemove);
+    } else {
+      throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
+    }
+  }
 }
diff --git a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathReplicatorTest.java b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathReplicatorTest.java
index d93f74a..2fe0657 100644
--- a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathReplicatorTest.java
+++ b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathReplicatorTest.java
@@ -1,16 +1,14 @@
 package net.minidev.json.test.actions;
 
-import net.minidev.json.actions.PathReplicator;
-import net.minidev.json.JSONArray;
-import net.minidev.json.JSONObject;
-import net.minidev.json.JSONValue;
-
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Stream;
-
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+import net.minidev.json.JSONValue;
+import net.minidev.json.actions.PathReplicator;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -20,180 +18,214 @@
  */
 public class PathReplicatorTest {
 
-	@SuppressWarnings("unchecked")
-	private static  T filter(T obj) {
-		if (obj == null)
-			return null;
-		if (obj instanceof String)
-			return (T)(((String)obj).replace("'", "\""));
-		return obj;
-	}
-	
-	public static Stream params() {
-		 return Stream.of(
-				//nulls, bad/empty keys
-				Arguments.of(null,                                        null,                           null                                         ),
-				Arguments.of(null,                                        "",                             null                                         ),
-				Arguments.of(null,                                        "k1",                           null                                         ),
-				Arguments.of(null,                                        new String[]{},                 null                                         ),
-				Arguments.of(null,                                        new JSONArray(),                null                                         ),
-				Arguments.of(null,                                        new ArrayList(0),       null                                         ),//5
-
-				//empty json, bad/empty keys
-				Arguments.of("{}",                                        null,                           "{}"                                         ),
-				Arguments.of("{}",                                        "",                             "{}"                                         ),
-				Arguments.of("{}",                                        "k1",                           "{}"                                         ),
-				Arguments.of("{}",                                        new String[]{},                 "{}"                                         ),
-				Arguments.of("{}",                                        new JSONArray(),                "{}"                                         ),
-				Arguments.of("{}",                                        new ArrayList(0),       "{}"                                         ),//11
-
-				//simple json, bad/empty keys
-				Arguments.of("{'k0':'v0'}",                               null,                           "{}"                                         ),
-				Arguments.of("{'k0':'v0'}",                               "",                             "{}"                                         ),
-				Arguments.of("{'k0':'v0'}",                               "k1",                           "{}"                                         ),
-				Arguments.of("{'k0':'v0'}",                               new String[]{},                 "{}"                                         ),
-				Arguments.of("{'k0':'v0'}",                               new JSONArray(),                "{}"                                         ),
-				Arguments.of("{'k0':'v0'}",                               new ArrayList(0),       "{}"                                         ),//17
-
-				//simple json, valid/invalid keys
-				Arguments.of("{'k0':'v0'}",                               "k0",                           "{'k0':'v0'}"                                ),
-				Arguments.of("{'k0':'v0'}",                               "v0",                           "{}"                                         ),
-				Arguments.of("{'k0':'v0'}",                               "k0.k1",                        "{}"                                         ),//20
-				Arguments.of("{'k0':'v0'}",                               "k1.k0",                        "{}"                                         ),
-				Arguments.of("{'k0':null}",                               "k0",                           "{'k0':null}"                                ),
-				Arguments.of("{'k0':null}",                               "v0",                           "{}"                                         ),
-
-				//key with dot char
-				Arguments.of("{'k0.k1':'v0'}",                            "k0",                           "{}"                                         ),
-				Arguments.of("{'k0.k1':'v0'}",                            "k1",                           "{}"                                         ),
-				Arguments.of("{'k0.k1':'v0'}",                            "k0.k1",                        "{}"                                         ),
-
-				// key with dot ambiguity
-				Arguments.of("{'k0.k1':'withDot','k0':{'k1':null}}",      "k0",                           "{'k0':{}}"                                  ),
-				Arguments.of("{'k0.k1':'withDot','k0':{'k1':null}}",      "k1",                           "{}"                                         ),
-				Arguments.of("{'k0.k1':'withDot','k0':{'k1':null}}",      "k0.k1",                        "{'k0':{'k1':null}}"                         ),
-				Arguments.of("{'k0':{'k1.k2':'dot','k1':{'k2':null}}}",   "k0.k1",                        "{'k0':{'k1':{}}}"                           ),
-				Arguments.of("{'k0':{'k1.k2':'dot','k1':{'k2':null}}}",   "k0.k1.k2",                     "{'k0':{'k1':{'k2':null}}}"                  ),
-				Arguments.of("{'k0':{'k1.k2':'dot','k1':{'k2':null}}}",   "k1.k2",                        "{}"                                         ),
-				Arguments.of("{'k0':{'k1.k2':'dot'},'k1':{'k2':'v2'}}}",  "k0",                           "{'k0':{}}}"                                 ),
-				Arguments.of("{'k0':{'k1.k2':'dot'},'k1':{'k2':'v2'}}}",  "k1.k2",                        "{'k1':{'k2':'v2'}}}"                        ),
-				Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}",   "k0.k2.k3.k4",                  "{}"                                         ),
-				Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}",   "k0.k2.k3",                     "{}"                                         ),
-				Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}",   "k0.k2",                        "{'k0':{'k2':{}}}"                           ),
-				Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}",   "k0",                           "{'k0':{}}"                                  ),//38
-
-				//ignore non-existent keys but keep good keys
-				Arguments.of("{'k0':'v0','k1':'v1'}",                     new String[]{"k0","k2"},         "{'k0':'v0'}"                               ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k0","k2"},         "{'k0':'v0'}"                               ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k0","k1.k2"},      "{'k0':'v0','k1':{'k2':'v2'}}"              ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k0","k0.k2"},      "{'k0':'v0'}"                               ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k0","k1.k2","k1"}, "{'k0':'v0','k1':{'k2':'v2'}}"              ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k0","k1"},         "{'k0':'v0','k1':{}}"                       ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k0","k1","k2"},    "{'k0':'v0','k1':{}}"                       ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k1.k2"},           "{'k1':{'k2':'v2'}}"                        ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k1.k2.k3"},        "{}"                                        ),
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k0.k1.k2"},        "{}"                                        ),//48
-				Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}",              new String[]{"k1.k0"},           "{}"                                        ),
-
-				//arrays - key inside array treated as child
-				Arguments.of("{'k0':{'k1':[1,2,3,4]}}",                                "k0",                                 "{'k0':{}}"                                    ),
-				Arguments.of("{'k0':{'k1':[1,2,3,4]}}",                                "k0.k1",                              "{'k0':{'k1':[1,2,3,4]}}"                      ),
-				Arguments.of("{'k0':{'k1':[1,{'k2':'v2'},3,4]}}",                      "k0",                                 "{'k0':{}}"                                    ),
-				Arguments.of("{'k0':{'k1':[1,{'k2':'v2'},3,4]}}",                      "k0.k1",                              "{'k0':{'k1':[1,{},3,4]}}"                     ),
-				Arguments.of("{'k0':{'k1':[1,{'k2':'v2'},3,4]}}",                      "k0.k1.k2",                           "{'k0':{'k1':[{'k2':'v2'}]}}"                  ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'},{'k2':'v2'}]}}",                "k0.k1",                              "{'k0':{'k1':[{},{}]}}"                        ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'},{'k2':'v2'}]}}",                "k0.k1.k2",                           "{'k0':{'k1':[{'k2':'v2'},{'k2':'v2'}]}}"      ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':'v4'}]}}",         "k0.k1.k2",                           "{'k0':{'k1':[{'k2':'v2'}]}}"                  ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':'v4'}]}}",         "k0.k3.k4",                           "{'k0':{'k3':[{'k4':'v4'}]}}"                  ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",  "k0.k1.k2",                           "{'k0':{'k1':[{'k2':'v2'}]}}"                  ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",  "k0.k3.k4",                           "{'k0':{'k3':[{'k4':{}}]}}"                    ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",  "k0.k3.k4.k5",                        "{'k0':{'k3':[{'k4':{'k5':'v5'}}]}}"           ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",  new String[]{"k0.k1", "k0.k3"},       "{'k0':{'k3':[{}],'k1':[{}]}}"                 ),
-				Arguments.of("{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",  new String[]{"k0.k1", "k0.k3.k4.k5"}, "{'k0':{'k3':[{'k4':{'k5':'v5'}}],'k1':[{}]}}" )
-		);
-	}
-
-	@ParameterizedTest
-	@MethodSource("params")
-	public void test(String jsonSource, Object pathsToCopy, Object expected) throws Exception {
-		jsonSource = filter(jsonSource);
-		pathsToCopy = filter(pathsToCopy);
-		expected = filter(expected);
-
-		JSONObject objectSource = jsonSource != null ? (JSONObject) JSONValue.parseWithException(jsonSource) : null;
-		PathReplicator copier = switchKeyToCopy(pathsToCopy);
-		JSONObject copied = copier.replicate(objectSource);
-		JSONObject expectedObj = expected != null ? (JSONObject) JSONValue.parseWithException((String) expected) : null;
-		assertEquals(expectedObj, copied);
-	}
-
-	@ParameterizedTest
-	@MethodSource("params")
-	public void test2(String jsonSource, Object pathsToCopy, Object expected) throws Exception {
-		jsonSource = filter(jsonSource);
-		pathsToCopy = filter(pathsToCopy);
-		expected = filter(expected);
-		JSONObject objectSource = jsonSource != null ? (JSONObject) JSONValue.parseWithException(jsonSource) : null;
-		PathReplicator copier = switchKeyToCopy2(pathsToCopy);
-		JSONObject copied = copier.replicate(objectSource);
-		JSONObject expectedObj = expected != null ? (JSONObject) JSONValue.parseWithException((String) expected) : null;
-		assertEquals(expectedObj, copied);
-	}
-
-	@SuppressWarnings("unchecked")
-	private PathReplicator switchKeyToCopy(Object pathsToCopy) {
-		long m = System.currentTimeMillis();
-		if (pathsToCopy == null && m % 4 == 0) {
-			// System.out.println("cast to String");
-			return new PathReplicator((String) null);
-		} else if (pathsToCopy == null && m % 4 == 1) {
-			// System.out.println("cast to String[]");
-			return new PathReplicator((String[]) null);
-		} else if (pathsToCopy == null && m % 4 == 2) {
-			// System.out.println("cast to JSONArray");
-			return new PathReplicator((JSONArray) null);
-		} else if (pathsToCopy == null && m % 4 == 3) {
-			// System.out.println("cast to List");
-			return new PathReplicator((List) null);
-		} else if (pathsToCopy instanceof String) {
-			return new PathReplicator((String) pathsToCopy);
-		} else if (pathsToCopy instanceof String[]) {
-			return new PathReplicator((String[]) pathsToCopy);
-		} else if (pathsToCopy instanceof JSONArray) {
-			return new PathReplicator((JSONArray) pathsToCopy);
-		} else if (pathsToCopy instanceof List) {
-			return new PathReplicator((List) pathsToCopy);
-		} else {
-			throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
-		}
-	}
-
-	@SuppressWarnings("unchecked")
-	private PathReplicator switchKeyToCopy2(Object pathsToCopy) {
-		long m = System.currentTimeMillis();
-		if (pathsToCopy == null && m % 4 == 0) {
-			// System.out.println("cast to String");
-			return new PathReplicator((String) null);
-		} else if (pathsToCopy == null && m % 4 == 1) {
-			// System.out.println("cast to String[]");
-			return new PathReplicator((String[]) null);
-		} else if (pathsToCopy == null && m % 4 == 2) {
-			// System.out.println("cast to JSONArray");
-			return new PathReplicator((JSONArray) null);
-		} else if (pathsToCopy == null && m % 4 == 3) {
-			// System.out.println("cast to List");
-			return new PathReplicator((List) null);
-		} else if (pathsToCopy instanceof String) {
-			return new PathReplicator((String) pathsToCopy);
-		} else if (pathsToCopy instanceof String[]) {
-			return new PathReplicator((String[]) pathsToCopy);
-		} else if (pathsToCopy instanceof JSONArray) {
-			return new PathReplicator((JSONArray) pathsToCopy);
-		} else if (pathsToCopy instanceof List) {
-			return new PathReplicator((List) pathsToCopy);
-		} else {
-			throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
-		}
-	}
-
-}
\ No newline at end of file
+  @SuppressWarnings("unchecked")
+  private static  T filter(T obj) {
+    if (obj == null) return null;
+    if (obj instanceof String) return (T) (((String) obj).replace("'", "\""));
+    return obj;
+  }
+
+  public static Stream params() {
+    return Stream.of(
+        // nulls, bad/empty keys
+        Arguments.of(null, null, null),
+        Arguments.of(null, "", null),
+        Arguments.of(null, "k1", null),
+        Arguments.of(null, new String[] {}, null),
+        Arguments.of(null, new JSONArray(), null),
+        Arguments.of(null, new ArrayList(0), null), // 5
+
+        // empty json, bad/empty keys
+        Arguments.of("{}", null, "{}"),
+        Arguments.of("{}", "", "{}"),
+        Arguments.of("{}", "k1", "{}"),
+        Arguments.of("{}", new String[] {}, "{}"),
+        Arguments.of("{}", new JSONArray(), "{}"),
+        Arguments.of("{}", new ArrayList(0), "{}"), // 11
+
+        // simple json, bad/empty keys
+        Arguments.of("{'k0':'v0'}", null, "{}"),
+        Arguments.of("{'k0':'v0'}", "", "{}"),
+        Arguments.of("{'k0':'v0'}", "k1", "{}"),
+        Arguments.of("{'k0':'v0'}", new String[] {}, "{}"),
+        Arguments.of("{'k0':'v0'}", new JSONArray(), "{}"),
+        Arguments.of("{'k0':'v0'}", new ArrayList(0), "{}"), // 17
+
+        // simple json, valid/invalid keys
+        Arguments.of("{'k0':'v0'}", "k0", "{'k0':'v0'}"),
+        Arguments.of("{'k0':'v0'}", "v0", "{}"),
+        Arguments.of("{'k0':'v0'}", "k0.k1", "{}"), // 20
+        Arguments.of("{'k0':'v0'}", "k1.k0", "{}"),
+        Arguments.of("{'k0':null}", "k0", "{'k0':null}"),
+        Arguments.of("{'k0':null}", "v0", "{}"),
+
+        // key with dot char
+        Arguments.of("{'k0.k1':'v0'}", "k0", "{}"),
+        Arguments.of("{'k0.k1':'v0'}", "k1", "{}"),
+        Arguments.of("{'k0.k1':'v0'}", "k0.k1", "{}"),
+
+        // key with dot ambiguity
+        Arguments.of("{'k0.k1':'withDot','k0':{'k1':null}}", "k0", "{'k0':{}}"),
+        Arguments.of("{'k0.k1':'withDot','k0':{'k1':null}}", "k1", "{}"),
+        Arguments.of("{'k0.k1':'withDot','k0':{'k1':null}}", "k0.k1", "{'k0':{'k1':null}}"),
+        Arguments.of("{'k0':{'k1.k2':'dot','k1':{'k2':null}}}", "k0.k1", "{'k0':{'k1':{}}}"),
+        Arguments.of(
+            "{'k0':{'k1.k2':'dot','k1':{'k2':null}}}", "k0.k1.k2", "{'k0':{'k1':{'k2':null}}}"),
+        Arguments.of("{'k0':{'k1.k2':'dot','k1':{'k2':null}}}", "k1.k2", "{}"),
+        Arguments.of("{'k0':{'k1.k2':'dot'},'k1':{'k2':'v2'}}}", "k0", "{'k0':{}}}"),
+        Arguments.of("{'k0':{'k1.k2':'dot'},'k1':{'k2':'v2'}}}", "k1.k2", "{'k1':{'k2':'v2'}}}"),
+        Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}", "k0.k2.k3.k4", "{}"),
+        Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}", "k0.k2.k3", "{}"),
+        Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}", "k0.k2", "{'k0':{'k2':{}}}"),
+        Arguments.of("{'k0':{'k1':'v1','k2':{'k3.k4':'dot'}}}", "k0", "{'k0':{}}"), // 38
+
+        // ignore non-existent keys but keep good keys
+        Arguments.of("{'k0':'v0','k1':'v1'}", new String[] {"k0", "k2"}, "{'k0':'v0'}"),
+        Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k0", "k2"}, "{'k0':'v0'}"),
+        Arguments.of(
+            "{'k0':'v0','k1':{'k2':'v2'}}",
+            new String[] {"k0", "k1.k2"},
+            "{'k0':'v0','k1':{'k2':'v2'}}"),
+        Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k0", "k0.k2"}, "{'k0':'v0'}"),
+        Arguments.of(
+            "{'k0':'v0','k1':{'k2':'v2'}}",
+            new String[] {"k0", "k1.k2", "k1"},
+            "{'k0':'v0','k1':{'k2':'v2'}}"),
+        Arguments.of(
+            "{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k0", "k1"}, "{'k0':'v0','k1':{}}"),
+        Arguments.of(
+            "{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k0", "k1", "k2"}, "{'k0':'v0','k1':{}}"),
+        Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k1.k2"}, "{'k1':{'k2':'v2'}}"),
+        Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k1.k2.k3"}, "{}"),
+        Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k0.k1.k2"}, "{}"), // 48
+        Arguments.of("{'k0':'v0','k1':{'k2':'v2'}}", new String[] {"k1.k0"}, "{}"),
+
+        // arrays - key inside array treated as child
+        Arguments.of("{'k0':{'k1':[1,2,3,4]}}", "k0", "{'k0':{}}"),
+        Arguments.of("{'k0':{'k1':[1,2,3,4]}}", "k0.k1", "{'k0':{'k1':[1,2,3,4]}}"),
+        Arguments.of("{'k0':{'k1':[1,{'k2':'v2'},3,4]}}", "k0", "{'k0':{}}"),
+        Arguments.of("{'k0':{'k1':[1,{'k2':'v2'},3,4]}}", "k0.k1", "{'k0':{'k1':[1,{},3,4]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[1,{'k2':'v2'},3,4]}}", "k0.k1.k2", "{'k0':{'k1':[{'k2':'v2'}]}}"),
+        Arguments.of("{'k0':{'k1':[{'k2':'v2'},{'k2':'v2'}]}}", "k0.k1", "{'k0':{'k1':[{},{}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'},{'k2':'v2'}]}}",
+            "k0.k1.k2",
+            "{'k0':{'k1':[{'k2':'v2'},{'k2':'v2'}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':'v4'}]}}",
+            "k0.k1.k2",
+            "{'k0':{'k1':[{'k2':'v2'}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':'v4'}]}}",
+            "k0.k3.k4",
+            "{'k0':{'k3':[{'k4':'v4'}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",
+            "k0.k1.k2",
+            "{'k0':{'k1':[{'k2':'v2'}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",
+            "k0.k3.k4",
+            "{'k0':{'k3':[{'k4':{}}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",
+            "k0.k3.k4.k5",
+            "{'k0':{'k3':[{'k4':{'k5':'v5'}}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",
+            new String[] {"k0.k1", "k0.k3"},
+            "{'k0':{'k3':[{}],'k1':[{}]}}"),
+        Arguments.of(
+            "{'k0':{'k1':[{'k2':'v2'}],'k3':[{'k4':{'k5':'v5'}}]}}",
+            new String[] {"k0.k1", "k0.k3.k4.k5"},
+            "{'k0':{'k3':[{'k4':{'k5':'v5'}}],'k1':[{}]}}"));
+  }
+
+  @ParameterizedTest
+  @MethodSource("params")
+  public void test(String jsonSource, Object pathsToCopy, Object expected) throws Exception {
+    jsonSource = filter(jsonSource);
+    pathsToCopy = filter(pathsToCopy);
+    expected = filter(expected);
+
+    JSONObject objectSource =
+        jsonSource != null ? (JSONObject) JSONValue.parseWithException(jsonSource) : null;
+    PathReplicator copier = switchKeyToCopy(pathsToCopy);
+    JSONObject copied = copier.replicate(objectSource);
+    JSONObject expectedObj =
+        expected != null ? (JSONObject) JSONValue.parseWithException((String) expected) : null;
+    assertEquals(expectedObj, copied);
+  }
+
+  @ParameterizedTest
+  @MethodSource("params")
+  public void test2(String jsonSource, Object pathsToCopy, Object expected) throws Exception {
+    jsonSource = filter(jsonSource);
+    pathsToCopy = filter(pathsToCopy);
+    expected = filter(expected);
+    JSONObject objectSource =
+        jsonSource != null ? (JSONObject) JSONValue.parseWithException(jsonSource) : null;
+    PathReplicator copier = switchKeyToCopy2(pathsToCopy);
+    JSONObject copied = copier.replicate(objectSource);
+    JSONObject expectedObj =
+        expected != null ? (JSONObject) JSONValue.parseWithException((String) expected) : null;
+    assertEquals(expectedObj, copied);
+  }
+
+  @SuppressWarnings("unchecked")
+  private PathReplicator switchKeyToCopy(Object pathsToCopy) {
+    long m = System.currentTimeMillis();
+    if (pathsToCopy == null && m % 4 == 0) {
+      // System.out.println("cast to String");
+      return new PathReplicator((String) null);
+    } else if (pathsToCopy == null && m % 4 == 1) {
+      // System.out.println("cast to String[]");
+      return new PathReplicator((String[]) null);
+    } else if (pathsToCopy == null && m % 4 == 2) {
+      // System.out.println("cast to JSONArray");
+      return new PathReplicator((JSONArray) null);
+    } else if (pathsToCopy == null && m % 4 == 3) {
+      // System.out.println("cast to List");
+      return new PathReplicator((List) null);
+    } else if (pathsToCopy instanceof String) {
+      return new PathReplicator((String) pathsToCopy);
+    } else if (pathsToCopy instanceof String[]) {
+      return new PathReplicator((String[]) pathsToCopy);
+    } else if (pathsToCopy instanceof JSONArray) {
+      return new PathReplicator((JSONArray) pathsToCopy);
+    } else if (pathsToCopy instanceof List) {
+      return new PathReplicator((List) pathsToCopy);
+    } else {
+      throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private PathReplicator switchKeyToCopy2(Object pathsToCopy) {
+    long m = System.currentTimeMillis();
+    if (pathsToCopy == null && m % 4 == 0) {
+      // System.out.println("cast to String");
+      return new PathReplicator((String) null);
+    } else if (pathsToCopy == null && m % 4 == 1) {
+      // System.out.println("cast to String[]");
+      return new PathReplicator((String[]) null);
+    } else if (pathsToCopy == null && m % 4 == 2) {
+      // System.out.println("cast to JSONArray");
+      return new PathReplicator((JSONArray) null);
+    } else if (pathsToCopy == null && m % 4 == 3) {
+      // System.out.println("cast to List");
+      return new PathReplicator((List) null);
+    } else if (pathsToCopy instanceof String) {
+      return new PathReplicator((String) pathsToCopy);
+    } else if (pathsToCopy instanceof String[]) {
+      return new PathReplicator((String[]) pathsToCopy);
+    } else if (pathsToCopy instanceof JSONArray) {
+      return new PathReplicator((JSONArray) pathsToCopy);
+    } else if (pathsToCopy instanceof List) {
+      return new PathReplicator((List) pathsToCopy);
+    } else {
+      throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
+    }
+  }
+}
diff --git a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathsRetainerTest.java b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathsRetainerTest.java
index 7c49b5e..16f18eb 100644
--- a/json-smart-action/src/test/java/net/minidev/json/test/actions/PathsRetainerTest.java
+++ b/json-smart-action/src/test/java/net/minidev/json/test/actions/PathsRetainerTest.java
@@ -1,139 +1,174 @@
 package net.minidev.json.test.actions;
 
-import net.minidev.json.actions.PathsRetainer;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
 import net.minidev.json.JSONArray;
 import net.minidev.json.JSONObject;
 import net.minidev.json.JSONValue;
+import net.minidev.json.actions.PathsRetainer;
 import net.minidev.json.actions.path.DotDelimiter;
 import net.minidev.json.parser.ParseException;
-
-// import org.junit.runner.RunWith;
-// import org.junit.runners.Parameterized;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Stream;
-
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
 /**
  * @author adoneitan@gmail.com
  */
 public class PathsRetainerTest {
-	
-	public static Stream params() {
-		 return Stream.of(
-			//nulls, bad/empty keys
-			Arguments.of(null,                                                  null,                           null                                                  ),
-			Arguments.of(null,                                                  "",                             null                                                  ),
-			Arguments.of(null,                                                  "k1",                           null                                                  ),
-			Arguments.of(null,                                                  new String[]{},                 null                                                  ),
-			Arguments.of(null,                                                  new JSONArray(),                null                                                  ),
-			Arguments.of(null,                                                  new ArrayList(0),       null                                                  ),//5
-			//empty json, bad/empty keys
-			Arguments.of("{}",                                                  null,                           "{}"                                                  ),
-			Arguments.of("{}",                                                  "",                             "{}"                                                  ),
-			Arguments.of("{}",                                                  "k1",                           "{}"                                                  ),
-			Arguments.of("{}",                                                  new String[]{},                 "{}"                                                  ),
-			Arguments.of("{}",                                                  new JSONArray(),                "{}"                                                  ),
-			Arguments.of("{}",                                                  new ArrayList(0),       "{}"                                                  ),//11
-			//simple json, bad/empty keys
-			Arguments.of("{\"k0\":\"v0\"}",                                     null,                           "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     "",                             "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     "k1",                           "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     new String[]{},                 "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     new JSONArray(),                "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     new ArrayList(0),       "{}"                                                  ),//17
-			//simple json, valid/invalid keys
-			Arguments.of("{\"k0\":\"v0\"}",                                     "k0",                           "{\"k0\":\"v0\"}"                                     ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     "v0",                           "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     "k0.k1",                        "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\"}",                                     "k1.k0",                        "{}"                                                  ),
-			Arguments.of("{\"k0\":null}",                                       "k0",                           "{\"k0\":null}"                                       ),
-			Arguments.of("{\"k0\":null}",                                       "v0",                           "{}"                                                  ),//23
-			//key with dot char
-			Arguments.of("{\"k0.k1\":\"v0\"}",                                  "k0",                           "{}"                                                  ),
-			Arguments.of("{\"k0.k1\":\"v0\"}",                                  "k1",                           "{}"                                                  ),
-			Arguments.of("{\"k0.k1\":\"v0\"}",                                  "k0.k1",                        "{}"                                                  ),
-			// key with dot ambiguity
-			Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}",        "k0",                           "{\"k0\":{}}"                                         ),//27
-			Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}",        "k1",                           "{}"                                                  ),
-			Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}",        "k0.k1",                        "{\"k0\":{\"k1\":null}}"                              ),//29
-			Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",   "k0.k1",                        "{\"k0\":{\"k1\":{}}}"                                ),
-			Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",   "k0.k1.k2",                     "{\"k0\":{\"k1\":{\"k2\":null}}}"                     ),//31
-			Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",   "k1.k2",                        "{}"                                                  ),
-			Arguments.of("{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}","k0",                           "{\"k0\":{}}}"                                        ),
-			Arguments.of("{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}","k1.k2",                        "{\"k1\":{\"k2\":\"v2\"}}}"                           ),
-			Arguments.of("{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0.k2.k3.k4",                  "{}"                                                  ),
-			Arguments.of("{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0.k2.k3",                     "{}"                                                  ),
-			Arguments.of("{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0.k2",                        "{\"k0\":{\"k2\":{}}}"                                ),
-			Arguments.of("{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0",                           "{\"k0\":{}}"                                         ),
 
-			//ignore non-existent keys but keep good keys
-			Arguments.of("{\"k0\":\"v0\",\"k1\":\"v1\"}",                      new String[]{"k0","k2"},         "{\"k0\":\"v0\"}"                                     ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k2"},         "{\"k0\":\"v0\"}"                                     ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1.k2"},      "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}"              ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k0.k2"},      "{\"k0\":\"v0\"}"                                     ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1.k2","k1"}, "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}"              ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1"},         "{\"k0\":\"v0\",\"k1\":{}}"                           ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0","k1","k2"},    "{\"k0\":\"v0\",\"k1\":{}}"                           ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k1.k2"},           "{\"k1\":{\"k2\":\"v2\"}}"                            ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k1.k2.k3"},        "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k0.k1.k2"},        "{}"                                                  ),
-			Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",             new String[]{"k1.k0"},           "{}"                                                  ),
-			//arrays - key inside array treated as child
-			Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",           "k0",                           "{\"k0\":{}}"                                         ),
-			Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",           "k0.k1",                        "{\"k0\":{\"k1\":[1,{},3,4]}}"                        ),
-			Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",           "k0.k1.k2",                     "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}"           ),
-			Arguments.of("{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}", "k0.k1",                        "{\"k0\":{\"k1\":[{},{}]}}"                           ),
-			Arguments.of("{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}", "k0.k1.k2",                     "{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}" )
-			);
-		}
+  public static Stream params() {
+    return Stream.of(
+        // nulls, bad/empty keys
+        Arguments.of(null, null, null),
+        Arguments.of(null, "", null),
+        Arguments.of(null, "k1", null),
+        Arguments.of(null, new String[] {}, null),
+        Arguments.of(null, new JSONArray(), null),
+        Arguments.of(null, new ArrayList(0), null), // 5
+        // empty json, bad/empty keys
+        Arguments.of("{}", null, "{}"),
+        Arguments.of("{}", "", "{}"),
+        Arguments.of("{}", "k1", "{}"),
+        Arguments.of("{}", new String[] {}, "{}"),
+        Arguments.of("{}", new JSONArray(), "{}"),
+        Arguments.of("{}", new ArrayList(0), "{}"), // 11
+        // simple json, bad/empty keys
+        Arguments.of("{\"k0\":\"v0\"}", null, "{}"),
+        Arguments.of("{\"k0\":\"v0\"}", "", "{}"),
+        Arguments.of("{\"k0\":\"v0\"}", "k1", "{}"),
+        Arguments.of("{\"k0\":\"v0\"}", new String[] {}, "{}"),
+        Arguments.of("{\"k0\":\"v0\"}", new JSONArray(), "{}"),
+        Arguments.of("{\"k0\":\"v0\"}", new ArrayList(0), "{}"), // 17
+        // simple json, valid/invalid keys
+        Arguments.of("{\"k0\":\"v0\"}", "k0", "{\"k0\":\"v0\"}"),
+        Arguments.of("{\"k0\":\"v0\"}", "v0", "{}"),
+        Arguments.of("{\"k0\":\"v0\"}", "k0.k1", "{}"),
+        Arguments.of("{\"k0\":\"v0\"}", "k1.k0", "{}"),
+        Arguments.of("{\"k0\":null}", "k0", "{\"k0\":null}"),
+        Arguments.of("{\"k0\":null}", "v0", "{}"), // 23
+        // key with dot char
+        Arguments.of("{\"k0.k1\":\"v0\"}", "k0", "{}"),
+        Arguments.of("{\"k0.k1\":\"v0\"}", "k1", "{}"),
+        Arguments.of("{\"k0.k1\":\"v0\"}", "k0.k1", "{}"),
+        // key with dot ambiguity
+        Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}", "k0", "{\"k0\":{}}"), // 27
+        Arguments.of("{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}", "k1", "{}"),
+        Arguments.of(
+            "{\"k0.k1\":\"withDot\",\"k0\":{\"k1\":null}}",
+            "k0.k1",
+            "{\"k0\":{\"k1\":null}}"), // 29
+        Arguments.of(
+            "{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}", "k0.k1", "{\"k0\":{\"k1\":{}}}"),
+        Arguments.of(
+            "{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}",
+            "k0.k1.k2",
+            "{\"k0\":{\"k1\":{\"k2\":null}}}"), // 31
+        Arguments.of("{\"k0\":{\"k1.k2\":\"dot\",\"k1\":{\"k2\":null}}}", "k1.k2", "{}"),
+        Arguments.of("{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}", "k0", "{\"k0\":{}}}"),
+        Arguments.of(
+            "{\"k0\":{\"k1.k2\":\"dot\"},\"k1\":{\"k2\":\"v2\"}}}",
+            "k1.k2",
+            "{\"k1\":{\"k2\":\"v2\"}}}"),
+        Arguments.of("{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0.k2.k3.k4", "{}"),
+        Arguments.of("{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0.k2.k3", "{}"),
+        Arguments.of(
+            "{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0.k2", "{\"k0\":{\"k2\":{}}}"),
+        Arguments.of("{\"k0\":{\"k1\":\"v1\",\"k2\":{\"k3.k4\":\"dot\"}}}", "k0", "{\"k0\":{}}"),
+
+        // ignore non-existent keys but keep good keys
+        Arguments.of("{\"k0\":\"v0\",\"k1\":\"v1\"}", new String[] {"k0", "k2"}, "{\"k0\":\"v0\"}"),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}", new String[] {"k0", "k2"}, "{\"k0\":\"v0\"}"),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1.k2"},
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}"),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k0.k2"},
+            "{\"k0\":\"v0\"}"),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1.k2", "k1"},
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}"),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1"},
+            "{\"k0\":\"v0\",\"k1\":{}}"),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k0", "k1", "k2"},
+            "{\"k0\":\"v0\",\"k1\":{}}"),
+        Arguments.of(
+            "{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}",
+            new String[] {"k1.k2"},
+            "{\"k1\":{\"k2\":\"v2\"}}"),
+        Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}", new String[] {"k1.k2.k3"}, "{}"),
+        Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}", new String[] {"k0.k1.k2"}, "{}"),
+        Arguments.of("{\"k0\":\"v0\",\"k1\":{\"k2\":\"v2\"}}", new String[] {"k1.k0"}, "{}"),
+        // arrays - key inside array treated as child
+        Arguments.of("{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}", "k0", "{\"k0\":{}}"),
+        Arguments.of(
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}", "k0.k1", "{\"k0\":{\"k1\":[1,{},3,4]}}"),
+        Arguments.of(
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}",
+            "k0.k1.k2",
+            "{\"k0\":{\"k1\":[1,{\"k2\":\"v2\"},3,4]}}"),
+        Arguments.of(
+            "{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}",
+            "k0.k1",
+            "{\"k0\":{\"k1\":[{},{}]}}"),
+        Arguments.of(
+            "{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}",
+            "k0.k1.k2",
+            "{\"k0\":{\"k1\":[{\"k2\":\"v2\"},{\"k2\":\"v2\"}]}}"));
+  }
 
-	
-	
-	@ParameterizedTest
-	@MethodSource("params")
-	public void test(String jsonToReduce, Object keyToKeep, String expectedReducedJson) throws ParseException {
-		JSONObject objectToReduce = jsonToReduce != null ? (JSONObject) JSONValue.parseWithException(jsonToReduce)
-				: null;
-		JSONObject expectedReducedObj = expectedReducedJson != null
-				? (JSONObject) JSONValue.parseWithException(expectedReducedJson)
-				: null;
-		PathsRetainer retainer = switchKeyToRemove(keyToKeep).with(new DotDelimiter().withAcceptDelimiterInNodeName(false));
-		JSONObject reducedObj = retainer.retain(objectToReduce);
-		assertEquals(expectedReducedObj, reducedObj);
-	}
+  @ParameterizedTest
+  @MethodSource("params")
+  public void test(String jsonToReduce, Object keyToKeep, String expectedReducedJson)
+      throws ParseException {
+    JSONObject objectToReduce =
+        jsonToReduce != null ? (JSONObject) JSONValue.parseWithException(jsonToReduce) : null;
+    JSONObject expectedReducedObj =
+        expectedReducedJson != null
+            ? (JSONObject) JSONValue.parseWithException(expectedReducedJson)
+            : null;
+    PathsRetainer retainer =
+        switchKeyToRemove(keyToKeep).with(new DotDelimiter().withAcceptDelimiterInNodeName(false));
+    JSONObject reducedObj = retainer.retain(objectToReduce);
+    assertEquals(expectedReducedObj, reducedObj);
+  }
 
-	@SuppressWarnings("unchecked")
-	private PathsRetainer switchKeyToRemove(Object keyToKeep) {
-		long m = System.currentTimeMillis();
-		if (keyToKeep == null && m % 4 == 0) {
-			// System.out.println("cast to String");
-			return new PathsRetainer((String) null);
-		} else if (keyToKeep == null && m % 4 == 1) {
-			// System.out.println("cast to String[]");
-			return new PathsRetainer((String[]) null);
-		} else if (keyToKeep == null && m % 4 == 2) {
-			// System.out.println("cast to JSONArray");
-			return new PathsRetainer((JSONArray) null);
-		} else if (keyToKeep == null && m % 4 == 3) {
-			// System.out.println("cast to List");
-			return new PathsRetainer((List) null);
-		} else if (keyToKeep instanceof String) {
-			return new PathsRetainer((String) keyToKeep);
-		} else if (keyToKeep instanceof String[]) {
-			return new PathsRetainer((String[]) keyToKeep);
-		} else if (keyToKeep instanceof JSONArray) {
-			return new PathsRetainer((JSONArray) keyToKeep);
-		} else if (keyToKeep instanceof List) {
-			return new PathsRetainer((List) keyToKeep);
-		} else {
-			throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
-		}
-	}
-}
\ No newline at end of file
+  @SuppressWarnings("unchecked")
+  private PathsRetainer switchKeyToRemove(Object keyToKeep) {
+    long m = System.currentTimeMillis();
+    if (keyToKeep == null && m % 4 == 0) {
+      // System.out.println("cast to String");
+      return new PathsRetainer((String) null);
+    } else if (keyToKeep == null && m % 4 == 1) {
+      // System.out.println("cast to String[]");
+      return new PathsRetainer((String[]) null);
+    } else if (keyToKeep == null && m % 4 == 2) {
+      // System.out.println("cast to JSONArray");
+      return new PathsRetainer((JSONArray) null);
+    } else if (keyToKeep == null && m % 4 == 3) {
+      // System.out.println("cast to List");
+      return new PathsRetainer((List) null);
+    } else if (keyToKeep instanceof String) {
+      return new PathsRetainer((String) keyToKeep);
+    } else if (keyToKeep instanceof String[]) {
+      return new PathsRetainer((String[]) keyToKeep);
+    } else if (keyToKeep instanceof JSONArray) {
+      return new PathsRetainer((JSONArray) keyToKeep);
+    } else if (keyToKeep instanceof List) {
+      return new PathsRetainer((List) keyToKeep);
+    } else {
+      throw new IllegalArgumentException("bad test setup: wrong type of key to remove");
+    }
+  }
+}
diff --git a/json-smart-action/src/test/java/net/minidev/json/test/actions/TreePathTest.java b/json-smart-action/src/test/java/net/minidev/json/test/actions/TreePathTest.java
index 617b6a8..7ca011c 100644
--- a/json-smart-action/src/test/java/net/minidev/json/test/actions/TreePathTest.java
+++ b/json-smart-action/src/test/java/net/minidev/json/test/actions/TreePathTest.java
@@ -1,94 +1,94 @@
 package net.minidev.json.test.actions;
 
-import net.minidev.json.actions.path.DotDelimiter;
-import net.minidev.json.actions.path.TreePath;
-import net.minidev.json.actions.path.PathDelimiter;
-
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import net.minidev.json.actions.path.DotDelimiter;
+import net.minidev.json.actions.path.PathDelimiter;
+import net.minidev.json.actions.path.TreePath;
 import org.junit.jupiter.api.Test;
 
 /**
  * @author adoneitan@gmail.com
  */
 public class TreePathTest {
-	private static final PathDelimiter delim = new DotDelimiter().withAcceptDelimiterInNodeName(true);
-
-	@Test
-	public void testIterator() {
-		TreePath jp = new TreePath("a.b.c", delim);
-		assertTrue(jp.nextIndex() == 0);
-		assertTrue(jp.prevIndex() == -1);
-		assertTrue("".equals(jp.curr()));
-		assertTrue("".equals(jp.origin()));
-		assertTrue("a.b.c".equals(jp.remainder()));
-		assertTrue(jp.hasNext());
-		assertFalse(jp.hasPrev());
-
-		jp.next();
-		assertTrue("a".equals(jp.curr()));
-		assertTrue("a".equals(jp.origin()));
-		assertTrue("b.c".equals(jp.remainder()));
-		assertTrue(jp.hasNext());
-		assertTrue(jp.hasPrev());
-
-		jp.next();
-		assertTrue("b".equals(jp.curr()));
-		assertTrue("a.b".equals(jp.origin()));
-		assertTrue("c".equals(jp.remainder()));
-		assertTrue(jp.hasNext());
-		assertTrue(jp.hasPrev());
-
-		jp.next();
-		assertTrue("c".equals(jp.curr()));
-		assertTrue("a.b.c".equals(jp.origin()));
-		assertTrue("".equals(jp.remainder()));
-		assertFalse(jp.hasNext());
-		assertTrue(jp.hasPrev());
-
-		/** the first prev() after a next only changes direction. see {@link ListIterator} for details */
-		jp.prev();
-		assertTrue("c".equals(jp.curr()));
-		assertTrue("a.b.c".equals(jp.origin()));
-		assertTrue("".equals(jp.remainder()));
-		assertTrue(jp.hasNext());
-		assertTrue(jp.hasPrev());
-
-		jp.prev();
-		assertTrue("b".equals(jp.curr()));
-		assertTrue("a.b".equals(jp.origin()));
-		assertTrue("c".equals(jp.remainder()));
-		assertTrue(jp.hasNext());
-		assertTrue(jp.hasPrev());
-
-		jp.prev();
-		assertTrue("a".equals(jp.curr()));
-		assertTrue("a".equals(jp.origin()));
-		assertTrue("b.c".equals(jp.remainder()));
-		assertTrue(jp.hasNext());
-		assertFalse(jp.hasPrev());
-	}
-
-	@Test
-	public void testSubPath() {
-		TreePath jp = new TreePath("a.b.c", delim);
-		assertTrue(jp.subPath(1, 2).equals("b.c"));
-	}
-
-	@Test
-	public void testClone() throws CloneNotSupportedException {
-		TreePath jp1 = new TreePath("a.b.c", delim);
-		TreePath jp2 = jp1.clone();
-		assertTrue(jp1.equals(jp2));
-
-		jp1.next();
-		TreePath jp3 = jp1.clone();
-		assertTrue(jp1.equals(jp3));
-
-		jp1.prev();
-		TreePath jp4 = jp1.clone();
-		assertTrue(jp1.equals(jp4));
-
-	}
-}
\ No newline at end of file
+  private static final PathDelimiter delim = new DotDelimiter().withAcceptDelimiterInNodeName(true);
+
+  @Test
+  public void testIterator() {
+    TreePath jp = new TreePath("a.b.c", delim);
+    assertTrue(jp.nextIndex() == 0);
+    assertTrue(jp.prevIndex() == -1);
+    assertTrue("".equals(jp.curr()));
+    assertTrue("".equals(jp.origin()));
+    assertTrue("a.b.c".equals(jp.remainder()));
+    assertTrue(jp.hasNext());
+    assertFalse(jp.hasPrev());
+
+    jp.next();
+    assertTrue("a".equals(jp.curr()));
+    assertTrue("a".equals(jp.origin()));
+    assertTrue("b.c".equals(jp.remainder()));
+    assertTrue(jp.hasNext());
+    assertTrue(jp.hasPrev());
+
+    jp.next();
+    assertTrue("b".equals(jp.curr()));
+    assertTrue("a.b".equals(jp.origin()));
+    assertTrue("c".equals(jp.remainder()));
+    assertTrue(jp.hasNext());
+    assertTrue(jp.hasPrev());
+
+    jp.next();
+    assertTrue("c".equals(jp.curr()));
+    assertTrue("a.b.c".equals(jp.origin()));
+    assertTrue("".equals(jp.remainder()));
+    assertFalse(jp.hasNext());
+    assertTrue(jp.hasPrev());
+
+    /**
+     * the first prev() after a next only changes direction. see {@link ListIterator} for details
+     */
+    jp.prev();
+    assertTrue("c".equals(jp.curr()));
+    assertTrue("a.b.c".equals(jp.origin()));
+    assertTrue("".equals(jp.remainder()));
+    assertTrue(jp.hasNext());
+    assertTrue(jp.hasPrev());
+
+    jp.prev();
+    assertTrue("b".equals(jp.curr()));
+    assertTrue("a.b".equals(jp.origin()));
+    assertTrue("c".equals(jp.remainder()));
+    assertTrue(jp.hasNext());
+    assertTrue(jp.hasPrev());
+
+    jp.prev();
+    assertTrue("a".equals(jp.curr()));
+    assertTrue("a".equals(jp.origin()));
+    assertTrue("b.c".equals(jp.remainder()));
+    assertTrue(jp.hasNext());
+    assertFalse(jp.hasPrev());
+  }
+
+  @Test
+  public void testSubPath() {
+    TreePath jp = new TreePath("a.b.c", delim);
+    assertTrue(jp.subPath(1, 2).equals("b.c"));
+  }
+
+  @Test
+  public void testClone() throws CloneNotSupportedException {
+    TreePath jp1 = new TreePath("a.b.c", delim);
+    TreePath jp2 = jp1.clone();
+    assertTrue(jp1.equals(jp2));
+
+    jp1.next();
+    TreePath jp3 = jp1.clone();
+    assertTrue(jp1.equals(jp3));
+
+    jp1.prev();
+    TreePath jp4 = jp1.clone();
+    assertTrue(jp1.equals(jp4));
+  }
+}
diff --git a/json-smart/pom.xml b/json-smart/pom.xml
index deb4d0b..e01082c 100644
--- a/json-smart/pom.xml
+++ b/json-smart/pom.xml
@@ -258,11 +258,15 @@ limitations under the License.
 				2.44.2
 				
 					
+						
+							src/main/java/**/*.java
+							src/test/java/**/*.java
+						
 						
 							1.25.2
 							
 							true
-							false
+							true
 						
 					
 				
diff --git a/json-smart/src/main/java/net/minidev/json/JSONArray.java b/json-smart/src/main/java/net/minidev/json/JSONArray.java
index b9c9a23..54c2b72 100644
--- a/json-smart/src/main/java/net/minidev/json/JSONArray.java
+++ b/json-smart/src/main/java/net/minidev/json/JSONArray.java
@@ -18,123 +18,112 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
-
 import net.minidev.json.reader.JsonWriter;
 
 /**
  * A JSON array. JSONObject supports java.util.List interface.
- * 
+ *
  * @author FangYidong <fangyidong@yahoo.com.cn>
  * @author Uriel Chemouni <uchemouni@gmail.com>
  */
-public class JSONArray extends ArrayList implements List, JSONAwareEx, JSONStreamAwareEx {
-	private static final long serialVersionUID = 9106884089231309568L;
-
-	public JSONArray() {
-	}
-
-	public JSONArray(int initialCapacity) {
-		super(initialCapacity);
-	}
-
-	public static String toJSONString(List list) {
-		return toJSONString(list, JSONValue.COMPRESSION);
-	}
-
-	/**
-	 * Convert a list to JSON text. The result is a JSON array. If this list is
-	 * also a JSONAware, JSONAware specific behaviours will be omitted at this
-	 * top level.
-	 * 
-	 * @see net.minidev.json.JSONValue#toJSONString(Object)
-	 * 
-	 * @param list
-	 * @param compression
-	 *            Indicate compression level
-	 * @return JSON text, or "null" if list is null.
-	 */
-	public static String toJSONString(List list, JSONStyle compression) {
-		StringBuilder sb = new StringBuilder();
-		try {
-			writeJSONString(list, sb, compression);
-		} catch (IOException e) {
-			// Can not append on a string builder
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * Encode a list into JSON text and write it to out. If this list is also a
-	 * JSONStreamAware or a JSONAware, JSONStreamAware and JSONAware specific
-	 * behaviours will be ignored at this top level.
-	 * 
-	 * @see JSONValue#writeJSONString(Object, Appendable)
-	 * 
-	 * @param list
-	 * @param out
-	 */
-	public static void writeJSONString(Iterable list, Appendable out, JSONStyle compression)
-			throws IOException {
-		if (list == null) {
-			out.append("null");
-			return;
-		}
-		JsonWriter.JSONIterableWriter.writeJSONString(list, out, compression);
-	}
-
-	public static void writeJSONString(List list, Appendable out) throws IOException {
-		writeJSONString(list, out, JSONValue.COMPRESSION);
-	}
-
-	/**
-	 * Appends the specified element and returns this.
-	 * Handy alternative to add(E e) method.
-	 *
-	 * @param element element to be appended to this array.
-	 * @return this
-	 */
-	public JSONArray appendElement(Object element) {
-		add(element);
-		return this;
-	}
-
-	public void merge(Object o2) {
-		JSONObject.merge(this, o2);
-	}
-
-	/**
-	 * Explicitly Serialize Object as JSon String
-	 */
-	public String toJSONString() {
-		return toJSONString(this, JSONValue.COMPRESSION);
-	}
-
-	public String toJSONString(JSONStyle compression) {
-		return toJSONString(this, compression);
-	}
-
-	/**
-	 * Override native toString()
-	 */
-	public String toString() {
-		return toJSONString();
-	}
-
-	/**
-	 * JSONAwareEx interface
-	 * 
-	 * @param compression
-	 *            compression param
-	 */
-	public String toString(JSONStyle compression) {
-		return toJSONString(compression);
-	}
-
-	public void writeJSONString(Appendable out) throws IOException {
-		writeJSONString(this, out, JSONValue.COMPRESSION);
-	}
-
-	public void writeJSONString(Appendable out, JSONStyle compression) throws IOException {
-		writeJSONString(this, out, compression);
-	}
+public class JSONArray extends ArrayList
+    implements List, JSONAwareEx, JSONStreamAwareEx {
+  private static final long serialVersionUID = 9106884089231309568L;
+
+  public JSONArray() {}
+
+  public JSONArray(int initialCapacity) {
+    super(initialCapacity);
+  }
+
+  public static String toJSONString(List list) {
+    return toJSONString(list, JSONValue.COMPRESSION);
+  }
+
+  /**
+   * Convert a list to JSON text. The result is a JSON array. If this list is also a JSONAware,
+   * JSONAware specific behaviours will be omitted at this top level.
+   *
+   * @see net.minidev.json.JSONValue#toJSONString(Object)
+   * @param list
+   * @param compression Indicate compression level
+   * @return JSON text, or "null" if list is null.
+   */
+  public static String toJSONString(List list, JSONStyle compression) {
+    StringBuilder sb = new StringBuilder();
+    try {
+      writeJSONString(list, sb, compression);
+    } catch (IOException e) {
+      // Can not append on a string builder
+    }
+    return sb.toString();
+  }
+
+  /**
+   * Encode a list into JSON text and write it to out. If this list is also a JSONStreamAware or a
+   * JSONAware, JSONStreamAware and JSONAware specific behaviours will be ignored at this top level.
+   *
+   * @see JSONValue#writeJSONString(Object, Appendable)
+   * @param list
+   * @param out
+   */
+  public static void writeJSONString(
+      Iterable list, Appendable out, JSONStyle compression) throws IOException {
+    if (list == null) {
+      out.append("null");
+      return;
+    }
+    JsonWriter.JSONIterableWriter.writeJSONString(list, out, compression);
+  }
+
+  public static void writeJSONString(List list, Appendable out)
+      throws IOException {
+    writeJSONString(list, out, JSONValue.COMPRESSION);
+  }
+
+  /**
+   * Appends the specified element and returns this. Handy alternative to add(E e) method.
+   *
+   * @param element element to be appended to this array.
+   * @return this
+   */
+  public JSONArray appendElement(Object element) {
+    add(element);
+    return this;
+  }
+
+  public void merge(Object o2) {
+    JSONObject.merge(this, o2);
+  }
+
+  /** Explicitly Serialize Object as JSon String */
+  public String toJSONString() {
+    return toJSONString(this, JSONValue.COMPRESSION);
+  }
+
+  public String toJSONString(JSONStyle compression) {
+    return toJSONString(this, compression);
+  }
+
+  /** Override native toString() */
+  public String toString() {
+    return toJSONString();
+  }
+
+  /**
+   * JSONAwareEx interface
+   *
+   * @param compression compression param
+   */
+  public String toString(JSONStyle compression) {
+    return toJSONString(compression);
+  }
+
+  public void writeJSONString(Appendable out) throws IOException {
+    writeJSONString(this, out, JSONValue.COMPRESSION);
+  }
+
+  public void writeJSONString(Appendable out, JSONStyle compression) throws IOException {
+    writeJSONString(this, out, compression);
+  }
 }
diff --git a/json-smart/src/main/java/net/minidev/json/JSONAware.java b/json-smart/src/main/java/net/minidev/json/JSONAware.java
index 459fed3..9bc5e74 100644
--- a/json-smart/src/main/java/net/minidev/json/JSONAware.java
+++ b/json-smart/src/main/java/net/minidev/json/JSONAware.java
@@ -16,14 +16,13 @@
  * limitations under the License.
  */
 /**
- * Beans that support customized output of JSON text shall implement this
- * interface.
- * 
+ * Beans that support customized output of JSON text shall implement this interface.
+ *
  * @author FangYidong <fangyidong@yahoo.com.cn>
  */
 public interface JSONAware {
-	/**
-	 * @return JSON text
-	 */
-	String toJSONString();
+  /**
+   * @return JSON text
+   */
+  String toJSONString();
 }
diff --git a/json-smart/src/main/java/net/minidev/json/JSONAwareEx.java b/json-smart/src/main/java/net/minidev/json/JSONAwareEx.java
index 9ae56ff..1fef8f6 100644
--- a/json-smart/src/main/java/net/minidev/json/JSONAwareEx.java
+++ b/json-smart/src/main/java/net/minidev/json/JSONAwareEx.java
@@ -17,15 +17,14 @@
  */
 /**
  * Beans that support advanced output of JSON text shall implement this interface.
- * 
- * Adding compressions and formating features
- * 
+ *
+ * 

Adding compressions and formating features + * * @author Uriel Chemouni <uchemouni@gmail.com> */ - public interface JSONAwareEx extends JSONAware { - /** - * @return JSON text - */ - String toJSONString(JSONStyle compression); + /** + * @return JSON text + */ + String toJSONString(JSONStyle compression); } diff --git a/json-smart/src/main/java/net/minidev/json/JSONNavi.java b/json-smart/src/main/java/net/minidev/json/JSONNavi.java index 242ffca..5c7fc3c 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONNavi.java +++ b/json-smart/src/main/java/net/minidev/json/JSONNavi.java @@ -19,749 +19,654 @@ import java.util.List; import java.util.Map; import java.util.Stack; - import net.minidev.json.writer.JsonReaderI; /** * A JQuery like Json editor, accessor. - * + * * @since 1.0.9 - * * @author Uriel Chemouni <uchemouni@gmail.com> */ public class JSONNavi { - private JsonReaderI mapper; - private T root; - - private Stack stack = new Stack(); - private Stack path = new Stack(); - - private Object current; - private boolean failure = false; - private String failureMessage; - - private boolean readonly = false; - private Object missingKey = null; - - public static JSONNavi newInstance() { - return new JSONNavi(JSONValue.defaultReader.DEFAULT_ORDERED); - } - - public static JSONNavi newInstanceObject() { - JSONNavi o = new JSONNavi(JSONValue.defaultReader.getMapper(JSONObject.class)); - o.object(); - return o; - } - - public static JSONNavi newInstanceArray() { - JSONNavi o = new JSONNavi(JSONValue.defaultReader.getMapper(JSONArray.class)); - o.array(); - return o; - } - - public JSONNavi(JsonReaderI mapper) { - this.mapper = mapper; - } - - @SuppressWarnings("unchecked") - public JSONNavi(String json) { - this.root = (T) JSONValue.parse(json); - this.current = this.root; - readonly = true; - } - - public JSONNavi(String json, JsonReaderI mapper) { - this.root = JSONValue.parse(json, mapper); - this.mapper = mapper; - this.current = this.root; - readonly = true; - } - - public JSONNavi(String json, Class mapTo) { - this.root = JSONValue.parse(json, mapTo); - this.mapper = JSONValue.defaultReader.getMapper(mapTo); - this.current = this.root; - readonly = true; - } - - /** - * return to root node - * - * @return the root node - */ - public JSONNavi root() { - this.current = this.root; - this.stack.clear(); - this.path.clear(); - this.failure = false; - this.missingKey = null; - this.failureMessage = null; - return this; - } - - public boolean hasFailure() { - return failure; - } - - public Object getCurrentObject() { - return current; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public Collection getKeys() { - if (current instanceof Map) - return ((Map) current).keySet(); - return null; - } - - public int getSize() { - if (current == null) - return 0; - if (isArray()) - return ((List) current).size(); - if (isObject()) - return ((Map) current).size(); - return 1; - } - - public String getString(String key) { - String v = null; - if (!hasKey(key)) - return v; - at(key); - v = asString(); - up(); - return v; - } - - public int getInt(String key) { - int v = 0; - if (!hasKey(key)) - return v; - at(key); - v = asInt(); - up(); - return v; - } - - public Integer getInteger(String key) { - Integer v = null; - if (!hasKey(key)) - return v; - at(key); - v = asIntegerObj(); - up(); - return v; - } - - public double getDouble(String key) { - double v = 0; - if (!hasKey(key)) - return v; - at(key); - v = asDouble(); - up(); - return v; - } - - public boolean hasKey(String key) { - if (!isObject()) - return false; - return o(current).containsKey(key); - } - - public JSONNavi at(String key) { - if (failure) - return this; - if (!isObject()) - object(); - if (!(current instanceof Map)) - return failure("current node is not an Object", key); - if (!o(current).containsKey(key)) { - if (readonly) - return failure("current Object have no key named " + key, key); - stack.add(current); - path.add(key); - current = null; - missingKey = key; - return this; - } - Object next = o(current).get(key); - stack.add(current); - path.add(key); - current = next; - return this; - } - - public Object get(String key) { - if (failure) - return this; - if (!isObject()) - object(); - if (!(current instanceof Map)) - return failure("current node is not an Object", key); - return o(current).get(key); - } - - public Object get(int index) { - if (failure) - return this; - if (!isArray()) - array(); - if (!(current instanceof List)) - return failure("current node is not an List", index); - return a(current).get(index); - } - - public JSONNavi set(String key, String value) { - object(); - if (failure) - return this; - o(current).put(key, value); - return this; - } - - public JSONNavi set(String key, Number value) { - object(); - if (failure) - return this; - o(current).put(key, value); - return this; - } - - /** - * write an value in the current object - * - * @param key - * key to access - * @param value - * new value - * @return this - */ - public JSONNavi set(String key, long value) { - return set(key, Long.valueOf(value)); - } - - /** - * write an value in the current object - * - * @param key - * key to access - * @param value - * new value - * @return this - */ - public JSONNavi set(String key, int value) { - return set(key, Integer.valueOf(value)); - } - - /** - * write an value in the current object - * - * @param key - * key to access - * @param value - * new value - * @return this - */ - public JSONNavi set(String key, double value) { - return set(key, Double.valueOf(value)); - } - - /** - * write an value in the current object - * - * @param key - * key to access - * @param value - * new value - * @return this - */ - public JSONNavi set(String key, float value) { - return set(key, Float.valueOf(value)); - } - - /** - * add value to the current arrays - * - * @param values - * to add - * @return this - */ - public JSONNavi add(Object... values) { - array(); - if (failure) - return this; - List list = a(current); - for (Object o : values) - list.add(o); - return this; - } - - /** - * get the current object value as String if the current Object is null - * return null. - * - * @return value as string - */ - public String asString() { - if (current == null) - return null; - if (current instanceof String) - return (String) current; - return current.toString(); - } - - /** - * get the current value as double if the current Object is null return - * Double.NaN - * - * @return value as double - */ - public double asDouble() { - if (current instanceof Number) - return ((Number) current).doubleValue(); - return Double.NaN; - } - - /** - * get the current object value as Double if the current Double can not be - * cast as Integer return null. - * - * @return value as Double - */ - public Double asDoubleObj() { - if (current == null) - return null; - if (current instanceof Number) { - if (current instanceof Double) - return (Double) current; - return Double.valueOf(((Number) current).doubleValue()); - } - return Double.NaN; - } - - /** - * get the current value as float if the current Object is null return - * Float.NaN - * - * @return value as float - */ - public float asFloat() { - if (current instanceof Number) - return ((Number) current).floatValue(); - return Float.NaN; - } - - /** - * get the current object value as Float if the current Float can not be - * cast as Integer return null. - */ - public Float asFloatObj() { - if (current == null) - return null; - if (current instanceof Number) { - if (current instanceof Float) - return (Float) current; - return Float.valueOf(((Number) current).floatValue()); - } - return Float.NaN; - } - - /** - * get the current value as int if the current Object is null return 0 - * - * @return value as Int - */ - public int asInt() { - if (current instanceof Number) - return ((Number) current).intValue(); - return 0; - } - - /** - * get the current object value as Integer if the current Object can not be - * cast as Integer return null. - * @return the current node value as an Integer - */ - public Integer asIntegerObj() { - if (current == null) - return null; - if (current instanceof Number) { - if (current instanceof Integer) - return (Integer) current; - if (current instanceof Long) { - Long l = (Long) current; - if (l.longValue() == l.intValue()) { - return Integer.valueOf(l.intValue()); - } - } - return null; - } - return null; - } - - /** - * get the current value as long if the current Object is null return 0 - * - * @return value as long - */ - public long asLong() { - if (current instanceof Number) - return ((Number) current).longValue(); - return 0L; - } - - /** - * get the current object value as Long if the current Object can not be - * cast as Long return null. - * - * @return value as Long - */ - public Long asLongObj() { - if (current == null) - return null; - if (current instanceof Number) { - if (current instanceof Long) - return (Long) current; - if (current instanceof Integer) - return Long.valueOf(((Number) current).longValue()); - return null; - } - return null; - } - - /** - * get the current value as boolean if the current Object is null or is not - * a boolean return false - * - * @return boolean - */ - public boolean asBoolean() { - if (current instanceof Boolean) - return ((Boolean) current).booleanValue(); - return false; - } - - /** - * get the current object value as Boolean if the current Object is not a - * Boolean return null. - * - * @return Boolean object - */ - public Boolean asBooleanObj() { - if (current == null) - return null; - if (current instanceof Boolean) - return (Boolean) current; - return null; - } - - /** - * Set current value as Json Object You can also skip this call, Objects can - * be create automatically. - * @return the current node as an object - */ - @SuppressWarnings("unchecked") - public JSONNavi object() { - if (failure) - return this; - if (current == null && readonly) - failure("Can not create Object child in readonly", null); - if (current != null) { - if (isObject()) - return this; - if (isArray()) - failure("can not use Object feature on Array.", null); - failure("Can not use current position as Object", null); - } else { - current = mapper.createObject(); - } - if (root == null) - root = (T) current; - else - store(); - return this; - } - - /** - * Set current value as Json Array You can also skip this call Arrays can be - * create automatically. - * - * @return the current node as an array - */ - @SuppressWarnings("unchecked") - public JSONNavi array() { - if (failure) - return this; - if (current == null && readonly) - failure("Can not create Array child in readonly", null); - if (current != null) { - if (isArray()) - return this; - if (isObject()) - failure("can not use Object feature on Array.", null); - failure("Can not use current position as Object", null); - } else { - current = mapper.createArray(); - } - if (root == null) - root = (T) current; - else - store(); - return this; - } - - /** - * set current value as Number - * @param num new value for the current node - * @return this for code chaining - */ - public JSONNavi set(Number num) { - if (failure) - return this; - current = num; - store(); - return this; - } - - /** - * set current value as Boolean - * @param bool new value for the current node - * - * @return this for code chaining - */ - public JSONNavi set(Boolean bool) { - if (failure) - return this; - current = bool; - store(); - return this; - } - - /** - * set current value as String - * @param text text value - * - * @return this for code chaining - */ - public JSONNavi set(String text) { - if (failure) - return this; - current = text; - store(); - return this; - } - - public T getRoot() { - return root; - } - - /** - * internal store current Object in current non existing localization - */ - private void store() { - Object parent = stack.peek(); - if (isObject(parent)) - o(parent).put((String) missingKey, current); - else if (isArray(parent)) { - int index = ((Number) missingKey).intValue(); - List lst = a(parent); - while (lst.size() <= index) - lst.add(null); - lst.set(index, current); - } - } - - /** - * is the current node is an array - * - * @return true if the current node is an array - */ - public boolean isArray() { - return isArray(current); - } - - /** - * is the current node is an object - * - * @return true if the current node is an object - */ - public boolean isObject() { - return isObject(current); - } - - /** - * check if Object is an Array - * - * @return true if the object is an array - */ - private boolean isArray(Object obj) { - if (obj == null) - return false; - return (obj instanceof List); - } - - /** - * check if Object is an Map - * @return true if the object node is an object - */ - private boolean isObject(Object obj) { - if (obj == null) - return false; - return (obj instanceof Map); - } - - /** - * internal cast to List - * @return casted object - */ - @SuppressWarnings("unchecked") - private List a(Object obj) { - return (List) obj; - } - - /** - * internal cast to Map - */ - @SuppressWarnings("unchecked") - private Map o(Object obj) { - return (Map) obj; - } - - /** - * Access to the index position. - * - * If index is less than 0 access element index from the end like in python. - * - * @param index - * 0 based desired position in Array - */ - public JSONNavi at(int index) { - if (failure) - return this; - if (!(current instanceof List)) - return failure("current node is not an Array", index); - @SuppressWarnings("unchecked") - List lst = ((List) current); - if (index < 0) { - index = lst.size() + index; - if (index < 0) - index = 0; - } - if (index >= lst.size()) - if (readonly) - return failure("Out of bound exception for index", index); - else { - stack.add(current); - path.add(index); - current = null; - missingKey = index; - return this; - } - Object next = lst.get(index); - stack.add(current); - path.add(index); - current = next; - return this; - } - - /** - * Access to last + 1 the index position. - * - * this method can only be used in writing mode. - */ - public JSONNavi atNext() { - if (failure) - return this; - if (!(current instanceof List)) - return failure("current node is not an Array", null); - @SuppressWarnings("unchecked") - List lst = ((List) current); - return at(lst.size()); - } - - /** - * call up() level times. - * - * @param level - * number of parent move. - */ - public JSONNavi up(int level) { - while (level-- > 0) { - if (stack.size() > 0) { - current = stack.pop(); - path.pop(); - } else - break; - } - return this; - } - - /** - * Move one level up in Json tree. if no more level up is available the - * statement had no effect. - */ - public JSONNavi up() { - if (stack.size() > 0) { - current = stack.pop(); - path.pop(); - } - return this; - } - - private final static JSONStyle ERROR_COMPRESS = new JSONStyle(JSONStyle.FLAG_PROTECT_4WEB); - - /** - * return the Object as a Json String - */ - public String toString() { - if (failure) - return JSONValue.toJSONString(failureMessage, ERROR_COMPRESS); - return JSONValue.toJSONString(root); - } - - /** - * return the Object as a Json String - * - * @param compression - */ - public String toString(JSONStyle compression) { - if (failure) - return JSONValue.toJSONString(failureMessage, compression); - return JSONValue.toJSONString(root, compression); - } - - /** - * Internally log errors. - */ - private JSONNavi failure(String err, Object jPathPostfix) { - failure = true; - StringBuilder sb = new StringBuilder(); - sb.append("Error: "); - sb.append(err); - sb.append(" at "); - sb.append(getJPath()); - if (jPathPostfix != null) - if (jPathPostfix instanceof Integer) - sb.append('[').append(jPathPostfix).append(']'); - else - sb.append('/').append(jPathPostfix); - this.failureMessage = sb.toString(); - return this; - } - - /** - * @return JPath to the current position - */ - public String getJPath() { - StringBuilder sb = new StringBuilder(); - for (Object o : path) { - if (o instanceof String) - sb.append('/').append(o.toString()); - else - sb.append('[').append(o.toString()).append(']'); - } - return sb.toString(); - } + private JsonReaderI mapper; + private T root; + + private Stack stack = new Stack(); + private Stack path = new Stack(); + + private Object current; + private boolean failure = false; + private String failureMessage; + + private boolean readonly = false; + private Object missingKey = null; + + public static JSONNavi newInstance() { + return new JSONNavi(JSONValue.defaultReader.DEFAULT_ORDERED); + } + + public static JSONNavi newInstanceObject() { + JSONNavi o = + new JSONNavi(JSONValue.defaultReader.getMapper(JSONObject.class)); + o.object(); + return o; + } + + public static JSONNavi newInstanceArray() { + JSONNavi o = + new JSONNavi(JSONValue.defaultReader.getMapper(JSONArray.class)); + o.array(); + return o; + } + + public JSONNavi(JsonReaderI mapper) { + this.mapper = mapper; + } + + @SuppressWarnings("unchecked") + public JSONNavi(String json) { + this.root = (T) JSONValue.parse(json); + this.current = this.root; + readonly = true; + } + + public JSONNavi(String json, JsonReaderI mapper) { + this.root = JSONValue.parse(json, mapper); + this.mapper = mapper; + this.current = this.root; + readonly = true; + } + + public JSONNavi(String json, Class mapTo) { + this.root = JSONValue.parse(json, mapTo); + this.mapper = JSONValue.defaultReader.getMapper(mapTo); + this.current = this.root; + readonly = true; + } + + /** + * return to root node + * + * @return the root node + */ + public JSONNavi root() { + this.current = this.root; + this.stack.clear(); + this.path.clear(); + this.failure = false; + this.missingKey = null; + this.failureMessage = null; + return this; + } + + public boolean hasFailure() { + return failure; + } + + public Object getCurrentObject() { + return current; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public Collection getKeys() { + if (current instanceof Map) return ((Map) current).keySet(); + return null; + } + + public int getSize() { + if (current == null) return 0; + if (isArray()) return ((List) current).size(); + if (isObject()) return ((Map) current).size(); + return 1; + } + + public String getString(String key) { + String v = null; + if (!hasKey(key)) return v; + at(key); + v = asString(); + up(); + return v; + } + + public int getInt(String key) { + int v = 0; + if (!hasKey(key)) return v; + at(key); + v = asInt(); + up(); + return v; + } + + public Integer getInteger(String key) { + Integer v = null; + if (!hasKey(key)) return v; + at(key); + v = asIntegerObj(); + up(); + return v; + } + + public double getDouble(String key) { + double v = 0; + if (!hasKey(key)) return v; + at(key); + v = asDouble(); + up(); + return v; + } + + public boolean hasKey(String key) { + if (!isObject()) return false; + return o(current).containsKey(key); + } + + public JSONNavi at(String key) { + if (failure) return this; + if (!isObject()) object(); + if (!(current instanceof Map)) return failure("current node is not an Object", key); + if (!o(current).containsKey(key)) { + if (readonly) return failure("current Object have no key named " + key, key); + stack.add(current); + path.add(key); + current = null; + missingKey = key; + return this; + } + Object next = o(current).get(key); + stack.add(current); + path.add(key); + current = next; + return this; + } + + public Object get(String key) { + if (failure) return this; + if (!isObject()) object(); + if (!(current instanceof Map)) return failure("current node is not an Object", key); + return o(current).get(key); + } + + public Object get(int index) { + if (failure) return this; + if (!isArray()) array(); + if (!(current instanceof List)) return failure("current node is not an List", index); + return a(current).get(index); + } + + public JSONNavi set(String key, String value) { + object(); + if (failure) return this; + o(current).put(key, value); + return this; + } + + public JSONNavi set(String key, Number value) { + object(); + if (failure) return this; + o(current).put(key, value); + return this; + } + + /** + * write an value in the current object + * + * @param key key to access + * @param value new value + * @return this + */ + public JSONNavi set(String key, long value) { + return set(key, Long.valueOf(value)); + } + + /** + * write an value in the current object + * + * @param key key to access + * @param value new value + * @return this + */ + public JSONNavi set(String key, int value) { + return set(key, Integer.valueOf(value)); + } + + /** + * write an value in the current object + * + * @param key key to access + * @param value new value + * @return this + */ + public JSONNavi set(String key, double value) { + return set(key, Double.valueOf(value)); + } + + /** + * write an value in the current object + * + * @param key key to access + * @param value new value + * @return this + */ + public JSONNavi set(String key, float value) { + return set(key, Float.valueOf(value)); + } + + /** + * add value to the current arrays + * + * @param values to add + * @return this + */ + public JSONNavi add(Object... values) { + array(); + if (failure) return this; + List list = a(current); + for (Object o : values) list.add(o); + return this; + } + + /** + * get the current object value as String if the current Object is null return null. + * + * @return value as string + */ + public String asString() { + if (current == null) return null; + if (current instanceof String) return (String) current; + return current.toString(); + } + + /** + * get the current value as double if the current Object is null return Double.NaN + * + * @return value as double + */ + public double asDouble() { + if (current instanceof Number) return ((Number) current).doubleValue(); + return Double.NaN; + } + + /** + * get the current object value as Double if the current Double can not be cast as Integer return + * null. + * + * @return value as Double + */ + public Double asDoubleObj() { + if (current == null) return null; + if (current instanceof Number) { + if (current instanceof Double) return (Double) current; + return Double.valueOf(((Number) current).doubleValue()); + } + return Double.NaN; + } + + /** + * get the current value as float if the current Object is null return Float.NaN + * + * @return value as float + */ + public float asFloat() { + if (current instanceof Number) return ((Number) current).floatValue(); + return Float.NaN; + } + + /** + * get the current object value as Float if the current Float can not be cast as Integer return + * null. + */ + public Float asFloatObj() { + if (current == null) return null; + if (current instanceof Number) { + if (current instanceof Float) return (Float) current; + return Float.valueOf(((Number) current).floatValue()); + } + return Float.NaN; + } + + /** + * get the current value as int if the current Object is null return 0 + * + * @return value as Int + */ + public int asInt() { + if (current instanceof Number) return ((Number) current).intValue(); + return 0; + } + + /** + * get the current object value as Integer if the current Object can not be cast as Integer return + * null. + * + * @return the current node value as an Integer + */ + public Integer asIntegerObj() { + if (current == null) return null; + if (current instanceof Number) { + if (current instanceof Integer) return (Integer) current; + if (current instanceof Long) { + Long l = (Long) current; + if (l.longValue() == l.intValue()) { + return Integer.valueOf(l.intValue()); + } + } + return null; + } + return null; + } + + /** + * get the current value as long if the current Object is null return 0 + * + * @return value as long + */ + public long asLong() { + if (current instanceof Number) return ((Number) current).longValue(); + return 0L; + } + + /** + * get the current object value as Long if the current Object can not be cast as Long return null. + * + * @return value as Long + */ + public Long asLongObj() { + if (current == null) return null; + if (current instanceof Number) { + if (current instanceof Long) return (Long) current; + if (current instanceof Integer) return Long.valueOf(((Number) current).longValue()); + return null; + } + return null; + } + + /** + * get the current value as boolean if the current Object is null or is not a boolean return false + * + * @return boolean + */ + public boolean asBoolean() { + if (current instanceof Boolean) return ((Boolean) current).booleanValue(); + return false; + } + + /** + * get the current object value as Boolean if the current Object is not a Boolean return null. + * + * @return Boolean object + */ + public Boolean asBooleanObj() { + if (current == null) return null; + if (current instanceof Boolean) return (Boolean) current; + return null; + } + + /** + * Set current value as Json Object You can also skip this call, Objects can be create + * automatically. + * + * @return the current node as an object + */ + @SuppressWarnings("unchecked") + public JSONNavi object() { + if (failure) return this; + if (current == null && readonly) failure("Can not create Object child in readonly", null); + if (current != null) { + if (isObject()) return this; + if (isArray()) failure("can not use Object feature on Array.", null); + failure("Can not use current position as Object", null); + } else { + current = mapper.createObject(); + } + if (root == null) root = (T) current; + else store(); + return this; + } + + /** + * Set current value as Json Array You can also skip this call Arrays can be create automatically. + * + * @return the current node as an array + */ + @SuppressWarnings("unchecked") + public JSONNavi array() { + if (failure) return this; + if (current == null && readonly) failure("Can not create Array child in readonly", null); + if (current != null) { + if (isArray()) return this; + if (isObject()) failure("can not use Object feature on Array.", null); + failure("Can not use current position as Object", null); + } else { + current = mapper.createArray(); + } + if (root == null) root = (T) current; + else store(); + return this; + } + + /** + * set current value as Number + * + * @param num new value for the current node + * @return this for code chaining + */ + public JSONNavi set(Number num) { + if (failure) return this; + current = num; + store(); + return this; + } + + /** + * set current value as Boolean + * + * @param bool new value for the current node + * @return this for code chaining + */ + public JSONNavi set(Boolean bool) { + if (failure) return this; + current = bool; + store(); + return this; + } + + /** + * set current value as String + * + * @param text text value + * @return this for code chaining + */ + public JSONNavi set(String text) { + if (failure) return this; + current = text; + store(); + return this; + } + + public T getRoot() { + return root; + } + + /** internal store current Object in current non existing localization */ + private void store() { + Object parent = stack.peek(); + if (isObject(parent)) o(parent).put((String) missingKey, current); + else if (isArray(parent)) { + int index = ((Number) missingKey).intValue(); + List lst = a(parent); + while (lst.size() <= index) lst.add(null); + lst.set(index, current); + } + } + + /** + * is the current node is an array + * + * @return true if the current node is an array + */ + public boolean isArray() { + return isArray(current); + } + + /** + * is the current node is an object + * + * @return true if the current node is an object + */ + public boolean isObject() { + return isObject(current); + } + + /** + * check if Object is an Array + * + * @return true if the object is an array + */ + private boolean isArray(Object obj) { + if (obj == null) return false; + return (obj instanceof List); + } + + /** + * check if Object is an Map + * + * @return true if the object node is an object + */ + private boolean isObject(Object obj) { + if (obj == null) return false; + return (obj instanceof Map); + } + + /** + * internal cast to List + * + * @return casted object + */ + @SuppressWarnings("unchecked") + private List a(Object obj) { + return (List) obj; + } + + /** internal cast to Map */ + @SuppressWarnings("unchecked") + private Map o(Object obj) { + return (Map) obj; + } + + /** + * Access to the index position. + * + *

If index is less than 0 access element index from the end like in python. + * + * @param index 0 based desired position in Array + */ + public JSONNavi at(int index) { + if (failure) return this; + if (!(current instanceof List)) return failure("current node is not an Array", index); + @SuppressWarnings("unchecked") + List lst = ((List) current); + if (index < 0) { + index = lst.size() + index; + if (index < 0) index = 0; + } + if (index >= lst.size()) + if (readonly) return failure("Out of bound exception for index", index); + else { + stack.add(current); + path.add(index); + current = null; + missingKey = index; + return this; + } + Object next = lst.get(index); + stack.add(current); + path.add(index); + current = next; + return this; + } + + /** + * Access to last + 1 the index position. + * + *

this method can only be used in writing mode. + */ + public JSONNavi atNext() { + if (failure) return this; + if (!(current instanceof List)) return failure("current node is not an Array", null); + @SuppressWarnings("unchecked") + List lst = ((List) current); + return at(lst.size()); + } + + /** + * call up() level times. + * + * @param level number of parent move. + */ + public JSONNavi up(int level) { + while (level-- > 0) { + if (stack.size() > 0) { + current = stack.pop(); + path.pop(); + } else break; + } + return this; + } + + /** + * Move one level up in Json tree. if no more level up is available the statement had no effect. + */ + public JSONNavi up() { + if (stack.size() > 0) { + current = stack.pop(); + path.pop(); + } + return this; + } + + private static final JSONStyle ERROR_COMPRESS = new JSONStyle(JSONStyle.FLAG_PROTECT_4WEB); + + /** return the Object as a Json String */ + public String toString() { + if (failure) return JSONValue.toJSONString(failureMessage, ERROR_COMPRESS); + return JSONValue.toJSONString(root); + } + + /** + * return the Object as a Json String + * + * @param compression + */ + public String toString(JSONStyle compression) { + if (failure) return JSONValue.toJSONString(failureMessage, compression); + return JSONValue.toJSONString(root, compression); + } + + /** Internally log errors. */ + private JSONNavi failure(String err, Object jPathPostfix) { + failure = true; + StringBuilder sb = new StringBuilder(); + sb.append("Error: "); + sb.append(err); + sb.append(" at "); + sb.append(getJPath()); + if (jPathPostfix != null) + if (jPathPostfix instanceof Integer) sb.append('[').append(jPathPostfix).append(']'); + else sb.append('/').append(jPathPostfix); + this.failureMessage = sb.toString(); + return this; + } + + /** + * @return JPath to the current position + */ + public String getJPath() { + StringBuilder sb = new StringBuilder(); + for (Object o : path) { + if (o instanceof String) sb.append('/').append(o.toString()); + else sb.append('[').append(o.toString()).append(']'); + } + return sb.toString(); + } } diff --git a/json-smart/src/main/java/net/minidev/json/JSONObject.java b/json-smart/src/main/java/net/minidev/json/JSONObject.java index 8a0fcfc..408e7ea 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONObject.java +++ b/json-smart/src/main/java/net/minidev/json/JSONObject.java @@ -18,267 +18,247 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; - import net.minidev.json.reader.JsonWriter; /** - * A JSON object. Key value pairs are unordered. JSONObject supports - * java.util.Map interface. - * + * A JSON object. Key value pairs are unordered. JSONObject supports java.util.Map interface. + * * @author FangYidong <fangyidong@yahoo.com.cn> * @author Uriel Chemouni <uchemouni@gmail.com> */ public class JSONObject extends HashMap implements JSONAwareEx, JSONStreamAwareEx { - private static final long serialVersionUID = -503443796854799292L; + private static final long serialVersionUID = -503443796854799292L; + + public JSONObject() { + super(); + } - public JSONObject() { - super(); - } + public JSONObject(int initialCapacity) { + super(initialCapacity); + } - public JSONObject(int initialCapacity) { - super(initialCapacity); - } + /** + * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F). + * It's the same as JSONValue.escape() only for compatibility here. + * + * @see JSONValue#escape(String) + */ + public static String escape(String s) { + return JSONValue.escape(s); + } - /** - * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters - * (U+0000 through U+001F). It's the same as JSONValue.escape() only for - * compatibility here. - * - * @see JSONValue#escape(String) - */ - public static String escape(String s) { - return JSONValue.escape(s); - } + public static String toJSONString(Map map) { + return toJSONString(map, JSONValue.COMPRESSION); + } - public static String toJSONString(Map map) { - return toJSONString(map, JSONValue.COMPRESSION); - } + /** + * Convert a map to JSON text. The result is a JSON object. If this map is also a JSONAware, + * JSONAware specific behaviours will be omitted at this top level. + * + * @see net.minidev.json.JSONValue#toJSONString(Object) + * @param map + * @return JSON text, or "null" if map is null. + */ + public static String toJSONString(Map map, JSONStyle compression) { + StringBuilder sb = new StringBuilder(); + try { + writeJSON(map, sb, compression); + } catch (IOException e) { + // can not append on a StringBuilder + } + return sb.toString(); + } - /** - * Convert a map to JSON text. The result is a JSON object. If this map is - * also a JSONAware, JSONAware specific behaviours will be omitted at this - * top level. - * - * @see net.minidev.json.JSONValue#toJSONString(Object) - * - * @param map - * @return JSON text, or "null" if map is null. - */ - public static String toJSONString(Map map, JSONStyle compression) { - StringBuilder sb = new StringBuilder(); - try { - writeJSON(map, sb, compression); - } catch (IOException e) { - // can not append on a StringBuilder - } - return sb.toString(); - } + /** Write a Key : value entry to a stream */ + public static void writeJSONKV(String key, Object value, Appendable out, JSONStyle compression) + throws IOException { + if (key == null) out.append("null"); + else if (!compression.mustProtectKey(key)) out.append(key); + else { + out.append('"'); + JSONValue.escape(key, out, compression); + out.append('"'); + } + out.append(':'); + if (value instanceof String) compression.writeString(out, (String) value); + else JSONValue.writeJSONString(value, out, compression); + } - /** - * Write a Key : value entry to a stream - */ - public static void writeJSONKV(String key, Object value, Appendable out, JSONStyle compression) throws IOException { - if (key == null) - out.append("null"); - else if (!compression.mustProtectKey(key)) - out.append(key); - else { - out.append('"'); - JSONValue.escape(key, out, compression); - out.append('"'); - } - out.append(':'); - if (value instanceof String) - compression.writeString(out, (String) value); - else - JSONValue.writeJSONString(value, out, compression); - } + /** + * Puts value to object and returns this. Handy alternative to put(String key, Object value) + * method. + * + * @param fieldName key with which the specified value is to be associated + * @param fieldValue value to be associated with the specified key + * @return this + */ + public JSONObject appendField(String fieldName, Object fieldValue) { + put(fieldName, fieldValue); + return this; + } - /** - * Puts value to object and returns this. - * Handy alternative to put(String key, Object value) method. - * - * @param fieldName key with which the specified value is to be associated - * @param fieldValue value to be associated with the specified key - * @return this - */ - public JSONObject appendField(String fieldName, Object fieldValue) { - put(fieldName, fieldValue); - return this; - } + /** + * A Simple Helper object to String + * + * @return a value.toString() or null + */ + public String getAsString(String key) { + Object obj = this.get(key); + if (obj == null) return null; + return obj.toString(); + } - /** - * A Simple Helper object to String - * - * @return a value.toString() or null - */ - public String getAsString(String key) { - Object obj = this.get(key); - if (obj == null) - return null; - return obj.toString(); - } + /** + * A Simple Helper cast an Object to an Number + * + * @return a Number or null + */ + public Number getAsNumber(String key) { + Object obj = this.get(key); + if (obj == null) return null; + if (obj instanceof Number) return (Number) obj; + return Long.valueOf(obj.toString()); + } - /** - * A Simple Helper cast an Object to an Number - * - * @return a Number or null - */ - public Number getAsNumber(String key) { - Object obj = this.get(key); - if (obj == null) - return null; - if (obj instanceof Number) - return (Number)obj; - return Long.valueOf(obj.toString()); - } - - // /** - // * return a Key:value entry as stream - // */ - // public static String toString(String key, Object value) { - // return toString(key, value, JSONValue.COMPRESSION); - // } + // /** + // * return a Key:value entry as stream + // */ + // public static String toString(String key, Object value) { + // return toString(key, value, JSONValue.COMPRESSION); + // } - // /** - // * return a Key:value entry as stream - // */ - // public static String toString(String key, Object value, JSONStyle - // compression) { - // StringBuilder sb = new StringBuilder(); - // try { - // writeJSONKV(key, value, sb, compression); - // } catch (IOException e) { - // // can not append on a StringBuilder - // } - // return sb.toString(); - // } + // /** + // * return a Key:value entry as stream + // */ + // public static String toString(String key, Object value, JSONStyle + // compression) { + // StringBuilder sb = new StringBuilder(); + // try { + // writeJSONKV(key, value, sb, compression); + // } catch (IOException e) { + // // can not append on a StringBuilder + // } + // return sb.toString(); + // } - /** - * Allows creation of a JSONObject from a Map. After that, both the - * generated JSONObject and the Map can be modified independently. - */ - public JSONObject(Map map) { - super(map); - } + /** + * Allows creation of a JSONObject from a Map. After that, both the generated JSONObject and the + * Map can be modified independently. + */ + public JSONObject(Map map) { + super(map); + } - public static void writeJSON(Map map, Appendable out) throws IOException { - writeJSON(map, out, JSONValue.COMPRESSION); - } + public static void writeJSON(Map map, Appendable out) + throws IOException { + writeJSON(map, out, JSONValue.COMPRESSION); + } - /** - * Encode a map into JSON text and write it to out. If this map is also a - * JSONAware or JSONStreamAware, JSONAware or JSONStreamAware specific - * behaviours will be ignored at this top level. - * - * @see JSONValue#writeJSONString(Object, Appendable) - */ - public static void writeJSON(Map map, Appendable out, JSONStyle compression) - throws IOException { - if (map == null) { - out.append("null"); - return; - } - JsonWriter.JSONMapWriter.writeJSONString(map, out, compression); - } + /** + * Encode a map into JSON text and write it to out. If this map is also a JSONAware or + * JSONStreamAware, JSONAware or JSONStreamAware specific behaviours will be ignored at this top + * level. + * + * @see JSONValue#writeJSONString(Object, Appendable) + */ + public static void writeJSON( + Map map, Appendable out, JSONStyle compression) throws IOException { + if (map == null) { + out.append("null"); + return; + } + JsonWriter.JSONMapWriter.writeJSONString(map, out, compression); + } - /** - * serialize Object as json to an stream - */ - public void writeJSONString(Appendable out) throws IOException { - writeJSON(this, out, JSONValue.COMPRESSION); - } + /** serialize Object as json to an stream */ + public void writeJSONString(Appendable out) throws IOException { + writeJSON(this, out, JSONValue.COMPRESSION); + } - /** - * serialize Object as json to an stream - */ - public void writeJSONString(Appendable out, JSONStyle compression) throws IOException { - writeJSON(this, out, compression); - } + /** serialize Object as json to an stream */ + public void writeJSONString(Appendable out, JSONStyle compression) throws IOException { + writeJSON(this, out, compression); + } - public void merge(Object o2) { - merge(this, o2, false); - } + public void merge(Object o2) { + merge(this, o2, false); + } - /** - * merge two JSONObject with overwrite or not - * overwrite = false will not overwrite existing key - * overwrite = true will overwrite the value with o2 of existing key - */ - public void merge(Object o2, boolean overwrite) { - merge(this, o2, overwrite); - } + /** + * merge two JSONObject with overwrite or not overwrite = false will not overwrite existing key + * overwrite = true will overwrite the value with o2 of existing key + */ + public void merge(Object o2, boolean overwrite) { + merge(this, o2, overwrite); + } - protected static JSONObject merge(JSONObject o1, Object o2, boolean overwrite) { - if (o2 == null) - return o1; - if (o2 instanceof JSONObject) - return merge(o1, (JSONObject) o2, overwrite); - throw new RuntimeException("JSON merge can not merge JSONObject with " + o2.getClass()); - } + protected static JSONObject merge(JSONObject o1, Object o2, boolean overwrite) { + if (o2 == null) return o1; + if (o2 instanceof JSONObject) return merge(o1, (JSONObject) o2, overwrite); + throw new RuntimeException("JSON merge can not merge JSONObject with " + o2.getClass()); + } - private static JSONObject merge(JSONObject o1, JSONObject o2, boolean overwrite) { - if (o2 == null) - return o1; - for (String key : o1.keySet()) { - Object value1 = o1.get(key); - Object value2 = o2.get(key); - if (value2 == null) - continue; - if (value1 instanceof JSONArray) { - o1.put(key, merge((JSONArray) value1, value2)); - continue; - } - if (value1 instanceof JSONObject) { - o1.put(key, merge((JSONObject) value1, value2, overwrite)); - continue; - } - if (value1.equals(value2)) - continue; - if (value1.getClass().equals(value2.getClass())) { - if (overwrite) { - o1.put(key, value2); - continue; - } - throw new RuntimeException("JSON merge can not merge two " + value1.getClass().getName() + " Object together"); - } - throw new RuntimeException("JSON merge can not merge " + value1.getClass().getName() + " with " + value2.getClass().getName()); - } - for (String key : o2.keySet()) { - if (o1.containsKey(key)) - continue; - o1.put(key, o2.get(key)); - } - return o1; - } + private static JSONObject merge(JSONObject o1, JSONObject o2, boolean overwrite) { + if (o2 == null) return o1; + for (String key : o1.keySet()) { + Object value1 = o1.get(key); + Object value2 = o2.get(key); + if (value2 == null) continue; + if (value1 instanceof JSONArray) { + o1.put(key, merge((JSONArray) value1, value2)); + continue; + } + if (value1 instanceof JSONObject) { + o1.put(key, merge((JSONObject) value1, value2, overwrite)); + continue; + } + if (value1.equals(value2)) continue; + if (value1.getClass().equals(value2.getClass())) { + if (overwrite) { + o1.put(key, value2); + continue; + } + throw new RuntimeException( + "JSON merge can not merge two " + value1.getClass().getName() + " Object together"); + } + throw new RuntimeException( + "JSON merge can not merge " + + value1.getClass().getName() + + " with " + + value2.getClass().getName()); + } + for (String key : o2.keySet()) { + if (o1.containsKey(key)) continue; + o1.put(key, o2.get(key)); + } + return o1; + } - protected static JSONArray merge(JSONArray o1, Object o2) { - if (o2 == null) - return o1; - if (o1 instanceof JSONArray) - return merge(o1, (JSONArray) o2); - o1.add(o2); - return o1; - } + protected static JSONArray merge(JSONArray o1, Object o2) { + if (o2 == null) return o1; + if (o1 instanceof JSONArray) return merge(o1, (JSONArray) o2); + o1.add(o2); + return o1; + } - private static JSONArray merge(JSONArray o1, JSONArray o2) { - o1.addAll(o2); - return o1; - } + private static JSONArray merge(JSONArray o1, JSONArray o2) { + o1.addAll(o2); + return o1; + } - public String toJSONString() { - return toJSONString(this, JSONValue.COMPRESSION); - } + public String toJSONString() { + return toJSONString(this, JSONValue.COMPRESSION); + } - public String toJSONString(JSONStyle compression) { - return toJSONString(this, compression); - } + public String toJSONString(JSONStyle compression) { + return toJSONString(this, compression); + } - public String toString(JSONStyle compression) { - return toJSONString(this, compression); - } + public String toString(JSONStyle compression) { + return toJSONString(this, compression); + } - public String toString() { - return toJSONString(this, JSONValue.COMPRESSION); - } + public String toString() { + return toJSONString(this, JSONValue.COMPRESSION); + } } diff --git a/json-smart/src/main/java/net/minidev/json/JSONStreamAware.java b/json-smart/src/main/java/net/minidev/json/JSONStreamAware.java index 1575093..447351d 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONStreamAware.java +++ b/json-smart/src/main/java/net/minidev/json/JSONStreamAware.java @@ -18,14 +18,11 @@ import java.io.IOException; /** - * Beans that support customized output of JSON text to a writer shall implement - * this interface. - * + * Beans that support customized output of JSON text to a writer shall implement this interface. + * * @author FangYidong <fangyidong@yahoo.com.cn> */ public interface JSONStreamAware { - /** - * write JSON string to out. - */ - void writeJSONString(Appendable out) throws IOException; + /** write JSON string to out. */ + void writeJSONString(Appendable out) throws IOException; } diff --git a/json-smart/src/main/java/net/minidev/json/JSONStreamAwareEx.java b/json-smart/src/main/java/net/minidev/json/JSONStreamAwareEx.java index 5e17d5b..16f20c9 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONStreamAwareEx.java +++ b/json-smart/src/main/java/net/minidev/json/JSONStreamAwareEx.java @@ -18,14 +18,11 @@ import java.io.IOException; /** - * Beans that support customized output of JSON text to a writer shall implement - * this interface. - * + * Beans that support customized output of JSON text to a writer shall implement this interface. + * * @author FangYidong <fangyidong@yahoo.com.cn> */ public interface JSONStreamAwareEx extends JSONStreamAware { - /** - * write JSON string to out. - */ - void writeJSONString(Appendable out, JSONStyle compression) throws IOException; + /** write JSON string to out. */ + void writeJSONString(Appendable out, JSONStyle compression) throws IOException; } diff --git a/json-smart/src/main/java/net/minidev/json/JSONStyle.java b/json-smart/src/main/java/net/minidev/json/JSONStyle.java index 2609e04..86ae8f8 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONStyle.java +++ b/json-smart/src/main/java/net/minidev/json/JSONStyle.java @@ -16,197 +16,164 @@ * limitations under the License. */ import java.io.IOException; - import net.minidev.json.JStylerObj.MustProtect; import net.minidev.json.JStylerObj.StringProtector; /** * JSONStyle object configure JSonSerializer reducing output size - * + * * @author Uriel Chemouni <uchemouni@gmail.com> */ public class JSONStyle { - /** - * for advanced usage sample see - * - * #see net.minidev.json.test.TestCompressorFlags - */ - public final static int FLAG_PROTECT_KEYS = 1; - public final static int FLAG_PROTECT_4WEB = 2; - public final static int FLAG_PROTECT_VALUES = 4; - /** - * AGRESSIVE have no effect without PROTECT_KEYS or PROTECT_VALUE - * - * AGRESSIVE mode allows Json-smart to not protect String containing - * special chars - */ - public final static int FLAG_AGRESSIVE = 8; - /** - * @since 2.1 - */ - public final static int FLAG_IGNORE_NULL = 16; - - public final static JSONStyle NO_COMPRESS = new JSONStyle(0); - public final static JSONStyle MAX_COMPRESS = new JSONStyle(-1); - /** - * @since 1.0.9.1 - */ - public final static JSONStyle LT_COMPRESS = new JSONStyle(FLAG_PROTECT_4WEB); - - private boolean _protectKeys; - private boolean _protect4Web; - private boolean _protectValues; - private boolean _ignore_null; - - private MustProtect mpKey; - private MustProtect mpValue; - - private StringProtector esc; - - public JSONStyle(int FLAG) { - _protectKeys = (FLAG & FLAG_PROTECT_KEYS) == 0; - _protectValues = (FLAG & FLAG_PROTECT_VALUES) == 0; - _protect4Web = (FLAG & FLAG_PROTECT_4WEB) == 0; - _ignore_null = (FLAG & FLAG_IGNORE_NULL) > 0; - - MustProtect mp; - if ((FLAG & FLAG_AGRESSIVE) > 0) - mp = JStylerObj.MP_AGGRESIVE; - else - mp = JStylerObj.MP_SIMPLE; - - if (_protectValues) - mpValue = JStylerObj.MP_TRUE; - else - mpValue = mp; - - if (_protectKeys) - mpKey = JStylerObj.MP_TRUE; - else - mpKey = mp; - - if (_protect4Web) - esc = JStylerObj.ESCAPE4Web; - else - esc = JStylerObj.ESCAPE_LT; - } - - public JSONStyle() { - this(0); - } - - public boolean protectKeys() { - return _protectKeys; - } - - public boolean protectValues() { - return _protectValues; - } - - public boolean protect4Web() { - return _protect4Web; - } - - public boolean ignoreNull() { - return _ignore_null; - } - - public boolean indent() { - return false; - } - - public boolean mustProtectKey(String s) { - return mpKey.mustBeProtect(s); - } - - public boolean mustProtectValue(String s) { - return mpValue.mustBeProtect(s); - } - - public void writeString(Appendable out, String value) throws IOException { - if (!this.mustProtectValue(value)) - out.append(value); - else { - out.append('"'); - JSONValue.escape(value, out, this); - out.append('"'); - } - } - - public void escape(String s, Appendable out) { - esc.escape(s, out); - } - - /** - * begin Object - */ - public void objectStart(Appendable out) throws IOException { - out.append('{'); - } - - /** - * terminate Object - */ - public void objectStop(Appendable out) throws IOException { - out.append('}'); - } - - /** - * Start the first Object element - */ - public void objectFirstStart(Appendable out) throws IOException { - } - - /** - * Start a new Object element - */ - public void objectNext(Appendable out) throws IOException { - out.append(','); - } - - /** - * End Of Object element - */ - public void objectElmStop(Appendable out) throws IOException { - } - - /** - * end of Key in json Object - */ - public void objectEndOfKey(Appendable out) throws IOException { - out.append(':'); - } - - /** - * Array start - */ - public void arrayStart(Appendable out) throws IOException { - out.append('['); - } - - /** - * Array Done - */ - public void arrayStop(Appendable out) throws IOException { - out.append(']'); - } - - /** - * Start the first Array element - */ - public void arrayfirstObject(Appendable out) throws IOException { - } - - /** - * Start a new Array element - */ - public void arrayNextElm(Appendable out) throws IOException { - out.append(','); - } - - /** - * End of an Array element - */ - public void arrayObjectEnd(Appendable out) throws IOException { - } + /** + * for advanced usage sample see + * + *

#see net.minidev.json.test.TestCompressorFlags + */ + public static final int FLAG_PROTECT_KEYS = 1; + + public static final int FLAG_PROTECT_4WEB = 2; + public static final int FLAG_PROTECT_VALUES = 4; + + /** + * AGRESSIVE have no effect without PROTECT_KEYS or PROTECT_VALUE + * + *

AGRESSIVE mode allows Json-smart to not protect String containing special chars + */ + public static final int FLAG_AGRESSIVE = 8; + + /** + * @since 2.1 + */ + public static final int FLAG_IGNORE_NULL = 16; + + public static final JSONStyle NO_COMPRESS = new JSONStyle(0); + public static final JSONStyle MAX_COMPRESS = new JSONStyle(-1); + + /** + * @since 1.0.9.1 + */ + public static final JSONStyle LT_COMPRESS = new JSONStyle(FLAG_PROTECT_4WEB); + + private boolean _protectKeys; + private boolean _protect4Web; + private boolean _protectValues; + private boolean _ignore_null; + + private MustProtect mpKey; + private MustProtect mpValue; + + private StringProtector esc; + + public JSONStyle(int FLAG) { + _protectKeys = (FLAG & FLAG_PROTECT_KEYS) == 0; + _protectValues = (FLAG & FLAG_PROTECT_VALUES) == 0; + _protect4Web = (FLAG & FLAG_PROTECT_4WEB) == 0; + _ignore_null = (FLAG & FLAG_IGNORE_NULL) > 0; + + MustProtect mp; + if ((FLAG & FLAG_AGRESSIVE) > 0) mp = JStylerObj.MP_AGGRESIVE; + else mp = JStylerObj.MP_SIMPLE; + + if (_protectValues) mpValue = JStylerObj.MP_TRUE; + else mpValue = mp; + + if (_protectKeys) mpKey = JStylerObj.MP_TRUE; + else mpKey = mp; + + if (_protect4Web) esc = JStylerObj.ESCAPE4Web; + else esc = JStylerObj.ESCAPE_LT; + } + + public JSONStyle() { + this(0); + } + + public boolean protectKeys() { + return _protectKeys; + } + + public boolean protectValues() { + return _protectValues; + } + + public boolean protect4Web() { + return _protect4Web; + } + + public boolean ignoreNull() { + return _ignore_null; + } + + public boolean indent() { + return false; + } + + public boolean mustProtectKey(String s) { + return mpKey.mustBeProtect(s); + } + + public boolean mustProtectValue(String s) { + return mpValue.mustBeProtect(s); + } + + public void writeString(Appendable out, String value) throws IOException { + if (!this.mustProtectValue(value)) out.append(value); + else { + out.append('"'); + JSONValue.escape(value, out, this); + out.append('"'); + } + } + + public void escape(String s, Appendable out) { + esc.escape(s, out); + } + + /** begin Object */ + public void objectStart(Appendable out) throws IOException { + out.append('{'); + } + + /** terminate Object */ + public void objectStop(Appendable out) throws IOException { + out.append('}'); + } + + /** Start the first Object element */ + public void objectFirstStart(Appendable out) throws IOException {} + + /** Start a new Object element */ + public void objectNext(Appendable out) throws IOException { + out.append(','); + } + + /** End Of Object element */ + public void objectElmStop(Appendable out) throws IOException {} + + /** end of Key in json Object */ + public void objectEndOfKey(Appendable out) throws IOException { + out.append(':'); + } + + /** Array start */ + public void arrayStart(Appendable out) throws IOException { + out.append('['); + } + + /** Array Done */ + public void arrayStop(Appendable out) throws IOException { + out.append(']'); + } + + /** Start the first Array element */ + public void arrayfirstObject(Appendable out) throws IOException {} + + /** Start a new Array element */ + public void arrayNextElm(Appendable out) throws IOException { + out.append(','); + } + + /** End of an Array element */ + public void arrayObjectEnd(Appendable out) throws IOException {} } diff --git a/json-smart/src/main/java/net/minidev/json/JSONUtil.java b/json-smart/src/main/java/net/minidev/json/JSONUtil.java index 0edb21d..4185507 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONUtil.java +++ b/json-smart/src/main/java/net/minidev/json/JSONUtil.java @@ -2,7 +2,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; - import net.minidev.asm.FieldFilter; import net.minidev.json.annotate.JsonIgnore; @@ -22,236 +21,181 @@ * limitations under the License. */ public class JSONUtil { - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Object convertToStrict(Object obj, Class dest) { - if (obj == null) - return null; - if (dest.isAssignableFrom(obj.getClass())) - return obj; - if (dest.isPrimitive()) { - if (dest == int.class) - if (obj instanceof Number) - return ((Number) obj).intValue(); - else - return Integer.valueOf(obj.toString()); - else if (dest == short.class) - if (obj instanceof Number) - return ((Number) obj).shortValue(); - else - return Short.valueOf(obj.toString()); - else if (dest == long.class) - if (obj instanceof Number) - return ((Number) obj).longValue(); - else - return Long.valueOf(obj.toString()); - else if (dest == byte.class) - if (obj instanceof Number) - return ((Number) obj).byteValue(); - else - return Byte.valueOf(obj.toString()); - else if (dest == float.class) - if (obj instanceof Number) - return ((Number) obj).floatValue(); - else - return Float.valueOf(obj.toString()); - else if (dest == double.class) - if (obj instanceof Number) - return ((Number) obj).doubleValue(); - else - return Double.valueOf(obj.toString()); - else if (dest == char.class) { - String asString = dest.toString(); - if (asString.length() > 0) - return Character.valueOf(asString.charAt(0)); - } else if (dest == boolean.class) { - return (Boolean) obj; - } - throw new RuntimeException("Primitive: Can not convert " + obj.getClass().getName() + " to " - + dest.getName()); - } else { - if (dest.isEnum()) - return Enum.valueOf((Class) dest, obj.toString()); - if (dest == Integer.class) - if (obj instanceof Number) - return Integer.valueOf(((Number) obj).intValue()); - else - return Integer.valueOf(obj.toString()); - if (dest == Long.class) - if (obj instanceof Number) - return Long.valueOf(((Number) obj).longValue()); - else - return Long.valueOf(obj.toString()); - if (dest == Short.class) - if (obj instanceof Number) - return Short.valueOf(((Number) obj).shortValue()); - else - return Short.valueOf(obj.toString()); - if (dest == Byte.class) - if (obj instanceof Number) - return Byte.valueOf(((Number) obj).byteValue()); - else - return Byte.valueOf(obj.toString()); - if (dest == Float.class) - if (obj instanceof Number) - return Float.valueOf(((Number) obj).floatValue()); - else - return Float.valueOf(obj.toString()); - if (dest == Double.class) - if (obj instanceof Number) - return Double.valueOf(((Number) obj).doubleValue()); - else - return Double.valueOf(obj.toString()); - if (dest == Character.class) { - String asString = dest.toString(); - if (asString.length() > 0) - return Character.valueOf(asString.charAt(0)); - } - throw new RuntimeException("Object: Can not Convert " + obj.getClass().getName() + " to " + dest.getName()); - } - } + @SuppressWarnings({"unchecked", "rawtypes"}) + public static Object convertToStrict(Object obj, Class dest) { + if (obj == null) return null; + if (dest.isAssignableFrom(obj.getClass())) return obj; + if (dest.isPrimitive()) { + if (dest == int.class) + if (obj instanceof Number) return ((Number) obj).intValue(); + else return Integer.valueOf(obj.toString()); + else if (dest == short.class) + if (obj instanceof Number) return ((Number) obj).shortValue(); + else return Short.valueOf(obj.toString()); + else if (dest == long.class) + if (obj instanceof Number) return ((Number) obj).longValue(); + else return Long.valueOf(obj.toString()); + else if (dest == byte.class) + if (obj instanceof Number) return ((Number) obj).byteValue(); + else return Byte.valueOf(obj.toString()); + else if (dest == float.class) + if (obj instanceof Number) return ((Number) obj).floatValue(); + else return Float.valueOf(obj.toString()); + else if (dest == double.class) + if (obj instanceof Number) return ((Number) obj).doubleValue(); + else return Double.valueOf(obj.toString()); + else if (dest == char.class) { + String asString = dest.toString(); + if (asString.length() > 0) return Character.valueOf(asString.charAt(0)); + } else if (dest == boolean.class) { + return (Boolean) obj; + } + throw new RuntimeException( + "Primitive: Can not convert " + obj.getClass().getName() + " to " + dest.getName()); + } else { + if (dest.isEnum()) return Enum.valueOf((Class) dest, obj.toString()); + if (dest == Integer.class) + if (obj instanceof Number) return Integer.valueOf(((Number) obj).intValue()); + else return Integer.valueOf(obj.toString()); + if (dest == Long.class) + if (obj instanceof Number) return Long.valueOf(((Number) obj).longValue()); + else return Long.valueOf(obj.toString()); + if (dest == Short.class) + if (obj instanceof Number) return Short.valueOf(((Number) obj).shortValue()); + else return Short.valueOf(obj.toString()); + if (dest == Byte.class) + if (obj instanceof Number) return Byte.valueOf(((Number) obj).byteValue()); + else return Byte.valueOf(obj.toString()); + if (dest == Float.class) + if (obj instanceof Number) return Float.valueOf(((Number) obj).floatValue()); + else return Float.valueOf(obj.toString()); + if (dest == Double.class) + if (obj instanceof Number) return Double.valueOf(((Number) obj).doubleValue()); + else return Double.valueOf(obj.toString()); + if (dest == Character.class) { + String asString = dest.toString(); + if (asString.length() > 0) return Character.valueOf(asString.charAt(0)); + } + throw new RuntimeException( + "Object: Can not Convert " + obj.getClass().getName() + " to " + dest.getName()); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static Object convertToX(Object obj, Class dest) { + if (obj == null) return null; + if (dest.isAssignableFrom(obj.getClass())) return obj; + if (dest.isPrimitive()) { + if (obj instanceof Number) return obj; + if (dest == int.class) return Integer.valueOf(obj.toString()); + else if (dest == short.class) return Short.valueOf(obj.toString()); + else if (dest == long.class) return Long.valueOf(obj.toString()); + else if (dest == byte.class) return Byte.valueOf(obj.toString()); + else if (dest == float.class) return Float.valueOf(obj.toString()); + else if (dest == double.class) return Double.valueOf(obj.toString()); + else if (dest == char.class) { + String asString = dest.toString(); + if (asString.length() > 0) return Character.valueOf(asString.charAt(0)); + } else if (dest == boolean.class) { + return (Boolean) obj; + } + throw new RuntimeException( + "Primitive: Can not convert " + obj.getClass().getName() + " to " + dest.getName()); + } else { + if (dest.isEnum()) return Enum.valueOf((Class) dest, obj.toString()); + if (dest == Integer.class) + if (obj instanceof Number) return Integer.valueOf(((Number) obj).intValue()); + else return Integer.valueOf(obj.toString()); + if (dest == Long.class) + if (obj instanceof Number) return Long.valueOf(((Number) obj).longValue()); + else return Long.valueOf(obj.toString()); + if (dest == Short.class) + if (obj instanceof Number) return Short.valueOf(((Number) obj).shortValue()); + else return Short.valueOf(obj.toString()); + if (dest == Byte.class) + if (obj instanceof Number) return Byte.valueOf(((Number) obj).byteValue()); + else return Byte.valueOf(obj.toString()); + if (dest == Float.class) + if (obj instanceof Number) return Float.valueOf(((Number) obj).floatValue()); + else return Float.valueOf(obj.toString()); + if (dest == Double.class) + if (obj instanceof Number) return Double.valueOf(((Number) obj).doubleValue()); + else return Double.valueOf(obj.toString()); + if (dest == Character.class) { + String asString = dest.toString(); + if (asString.length() > 0) return Character.valueOf(asString.charAt(0)); + } + throw new RuntimeException( + "Object: Can not Convert " + obj.getClass().getName() + " to " + dest.getName()); + } + } - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Object convertToX(Object obj, Class dest) { - if (obj == null) - return null; - if (dest.isAssignableFrom(obj.getClass())) - return obj; - if (dest.isPrimitive()) { - if (obj instanceof Number) - return obj; - if (dest == int.class) - return Integer.valueOf(obj.toString()); - else if (dest == short.class) - return Short.valueOf(obj.toString()); - else if (dest == long.class) - return Long.valueOf(obj.toString()); - else if (dest == byte.class) - return Byte.valueOf(obj.toString()); - else if (dest == float.class) - return Float.valueOf(obj.toString()); - else if (dest == double.class) - return Double.valueOf(obj.toString()); - else if (dest == char.class) { - String asString = dest.toString(); - if (asString.length() > 0) - return Character.valueOf(asString.charAt(0)); - } else if (dest == boolean.class) { - return (Boolean) obj; - } - throw new RuntimeException("Primitive: Can not convert " + obj.getClass().getName() + " to " - + dest.getName()); - } else { - if (dest.isEnum()) - return Enum.valueOf((Class) dest, obj.toString()); - if (dest == Integer.class) - if (obj instanceof Number) - return Integer.valueOf(((Number) obj).intValue()); - else - return Integer.valueOf(obj.toString()); - if (dest == Long.class) - if (obj instanceof Number) - return Long.valueOf(((Number) obj).longValue()); - else - return Long.valueOf(obj.toString()); - if (dest == Short.class) - if (obj instanceof Number) - return Short.valueOf(((Number) obj).shortValue()); - else - return Short.valueOf(obj.toString()); - if (dest == Byte.class) - if (obj instanceof Number) - return Byte.valueOf(((Number) obj).byteValue()); - else - return Byte.valueOf(obj.toString()); - if (dest == Float.class) - if (obj instanceof Number) - return Float.valueOf(((Number) obj).floatValue()); - else - return Float.valueOf(obj.toString()); - if (dest == Double.class) - if (obj instanceof Number) - return Double.valueOf(((Number) obj).doubleValue()); - else - return Double.valueOf(obj.toString()); - if (dest == Character.class) { - String asString = dest.toString(); - if (asString.length() > 0) - return Character.valueOf(asString.charAt(0)); - } - throw new RuntimeException("Object: Can not Convert " + obj.getClass().getName() + " to " + dest.getName()); - } - } + public static final JsonSmartFieldFilter JSON_SMART_FIELD_FILTER = new JsonSmartFieldFilter(); - public final static JsonSmartFieldFilter JSON_SMART_FIELD_FILTER = new JsonSmartFieldFilter(); + public static class JsonSmartFieldFilter implements FieldFilter { - public static class JsonSmartFieldFilter implements FieldFilter { + public boolean canUse(Field field) { + JsonIgnore ignore = field.getAnnotation(JsonIgnore.class); + if (ignore != null && ignore.value()) return false; + return true; + } - public boolean canUse(Field field) { - JsonIgnore ignore = field.getAnnotation(JsonIgnore.class); - if (ignore != null && ignore.value()) - return false; - return true; - } + public boolean canUse(Field field, Method method) { + JsonIgnore ignore = method.getAnnotation(JsonIgnore.class); + if (ignore != null && ignore.value()) return false; + return true; + } - public boolean canUse(Field field, Method method) { - JsonIgnore ignore = method.getAnnotation(JsonIgnore.class); - if (ignore != null && ignore.value()) - return false; - return true; - } + public boolean canRead(Field field) { + return true; + } - public boolean canRead(Field field) { - return true; - } + public boolean canWrite(Field field) { + return true; + } + } - public boolean canWrite(Field field) { - return true; - } - } - public static String getSetterName(String key) { - int len = key.length(); - char[] b = new char[len + 3]; - b[0] = 's'; - b[1] = 'e'; - b[2] = 't'; - char c = key.charAt(0); - if (c >= 'a' && c <= 'z') - c += 'A' - 'a'; - b[3] = c; - for (int i = 1; i < len; i++) { - b[i + 3] = key.charAt(i); - } - return new String(b); - } + public static String getSetterName(String key) { + int len = key.length(); + char[] b = new char[len + 3]; + b[0] = 's'; + b[1] = 'e'; + b[2] = 't'; + char c = key.charAt(0); + if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + b[3] = c; + for (int i = 1; i < len; i++) { + b[i + 3] = key.charAt(i); + } + return new String(b); + } - public static String getGetterName(String key) { - int len = key.length(); - char[] b = new char[len + 3]; - b[0] = 'g'; - b[1] = 'e'; - b[2] = 't'; - char c = key.charAt(0); - if (c >= 'a' && c <= 'z') - c += 'A' - 'a'; - b[3] = c; - for (int i = 1; i < len; i++) { - b[i + 3] = key.charAt(i); - } - return new String(b); - } + public static String getGetterName(String key) { + int len = key.length(); + char[] b = new char[len + 3]; + b[0] = 'g'; + b[1] = 'e'; + b[2] = 't'; + char c = key.charAt(0); + if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + b[3] = c; + for (int i = 1; i < len; i++) { + b[i + 3] = key.charAt(i); + } + return new String(b); + } - public static String getIsName(String key) { - int len = key.length(); - char[] b = new char[len + 2]; - b[0] = 'i'; - b[1] = 's'; - char c = key.charAt(0); - if (c >= 'a' && c <= 'z') - c += 'A' - 'a'; - b[2] = c; - for (int i = 1; i < len; i++) { - b[i + 2] = key.charAt(i); - } - return new String(b); - } + public static String getIsName(String key) { + int len = key.length(); + char[] b = new char[len + 2]; + b[0] = 'i'; + b[1] = 's'; + char c = key.charAt(0); + if (c >= 'a' && c <= 'z') c += 'A' - 'a'; + b[2] = c; + for (int i = 1; i < len; i++) { + b[i + 2] = key.charAt(i); + } + return new String(b); + } } diff --git a/json-smart/src/main/java/net/minidev/json/JSONValue.java b/json-smart/src/main/java/net/minidev/json/JSONValue.java index 567b635..95fdee1 100644 --- a/json-smart/src/main/java/net/minidev/json/JSONValue.java +++ b/json-smart/src/main/java/net/minidev/json/JSONValue.java @@ -23,7 +23,6 @@ import java.io.Reader; import java.util.List; import java.util.Map; - import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; import net.minidev.json.reader.JsonWriter; @@ -35,645 +34,593 @@ import net.minidev.json.writer.UpdaterMapper; /** - * JSONValue is the helper class In most of case you should use those static - * method to user JSON-smart - * - * - * The most commonly use method are {@link #parse(String)} - * {@link #toJSONString(Object)} - * + * JSONValue is the helper class In most of case you should use those static method to user + * JSON-smart + * + *

The most commonly use method are {@link #parse(String)} {@link #toJSONString(Object)} + * * @author Uriel Chemouni <uchemouni@gmail.com> */ public class JSONValue { - /** - * Global default compression type - */ - public static JSONStyle COMPRESSION = JSONStyle.NO_COMPRESS; - - /** - * Parse JSON text into java object from the input source. Please use - * parseWithException() if you don't want to ignore the exception. if you - * want strict input check use parseStrict() - * - * @see JSONParser#parse(Reader) - * @see #parseWithException(Reader) - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - * - */ - public static Object parse(InputStream in) { - try { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in); - } catch (Exception e) { - return null; - } - } - - /** - * Parse JSON text into java object from the input source. Please use - * parseWithException() if you don't want to ignore the exception. if you - * want strict input check use parseStrict() - * - * @see JSONParser#parse(Reader) - * @see #parseWithException(Reader) - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - * - */ - public static Object parse(byte[] in) { - try { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * mapTo can be a bean - * - * @since 2.0 - */ - public static T parse(InputStream in, Class mapTo) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, defaultReader.getMapper(mapTo)); - } catch (Exception e) { - return null; - } - } - - /** - * Parse JSON text into java object from the input source. Please use - * parseWithException() if you don't want to ignore the exception. if you - * want strict input check use parseStrict() - * - * @see JSONParser#parse(Reader) - * @see #parseWithException(Reader) - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - * - */ - public static Object parse(Reader in) { - try { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * mapTo can be a bean - * - * @since 2.0 - */ - public static T parse(byte[] in, Class mapTo) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, defaultReader.getMapper(mapTo)); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * mapTo can be a bean - * - * @since 2.0 - */ - public static T parse(Reader in, Class mapTo) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, defaultReader.getMapper(mapTo)); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * mapTo can be a bean - * - * @since 2.0 - */ - public static T parse(Reader in, T toUpdate) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, new UpdaterMapper(defaultReader, toUpdate)); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * @since 2.0 - */ - protected static T parse(Reader in, JsonReaderI mapper) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, mapper); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * mapTo can be a bean - * - * @since 2.0 - */ - public static T parse(String in, Class mapTo) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, defaultReader.getMapper(mapTo)); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * mapTo can be a bean - * - * @since 2.0 - */ - public static T parse(InputStream in, T toUpdate) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, new UpdaterMapper(defaultReader, toUpdate)); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * mapTo can be a bean - * - * @since 2.0 - */ - public static T parse(String in, T toUpdate) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, new UpdaterMapper(defaultReader, toUpdate)); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * @since 2.0 - */ - protected static T parse(byte[] in, JsonReaderI mapper) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, mapper); - } catch (Exception e) { - return null; - } - } - - /** - * Parse input json as a mapTo class - * - * @since 2.0 - */ - protected static T parse(String in, JsonReaderI mapper) { - try { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, mapper); - } catch (Exception e) { - return null; - } - } - - /** - * Parse JSON text into java object from the input source. Please use - * parseWithException() if you don't want to ignore the exception. if you - * want strict input check use parseStrict() - * - * @see JSONParser#parse(String) - * @see #parseWithException(String) - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - * - */ - public static Object parse(String s) { - try { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(s); - } catch (Exception e) { - return null; - } - } - - /** - * Parse Json input to a java Object keeping element order - * - * @param in json source - * - * @return a OrderedMap preserving field order. - * - * @since 1.0.6.1 - */ - public static Object parseKeepingOrder(Reader in) { - try { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT_ORDERED); - } catch (Exception e) { - return null; - } - } - - /** - * Parse Json input to a java Object keeping element order - * - * @param in json source - * - * @return a OrderedMap preserving field order.\ - * - * @since 1.0.6.1 - */ - public static Object parseKeepingOrder(String in) { - try { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT_ORDERED); - } catch (Exception e) { - return null; - } - } - - /** - * Reformat Json input keeping element order - * - * @param input text to parse - * @param style parse options - * - * @since 1.0.6.2 - * - * @return json string - */ - public static String compress(String input, JSONStyle style) { - try { - StringBuilder sb = new StringBuilder(); - new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(input, new CompessorMapper(defaultReader, sb, style)); - return sb.toString(); - } catch (Exception e) { - return input; - } - } - - /** - * Compress Json input keeping element order - * - * @param input text to parse - * - * @since 1.0.6.1 - * - * need to be rewrite in 2.0 - */ - public static String compress(String input) { - return compress(input, JSONStyle.MAX_COMPRESS); - } - - /** - * Compress Json input keeping element order - * @param input text to parse - * - * @since 1.0.6.1 - */ - public static String uncompress(String input) { - return compress(input, JSONStyle.NO_COMPRESS); - } - - /** - * Parse JSON text into java object from the input source. - * - * @param in source to parse - * - * @see JSONParser - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - */ - public static Object parseWithException(byte[] in) throws IOException, ParseException { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT); - } - - /** - * Parse JSON text into java object from the input source. - * - * @param in source to parse - * @see JSONParser - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - */ - public static Object parseWithException(InputStream in) throws IOException, ParseException { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT); - } - - /** - * Parse JSON text into java object from the input source. - * - * @param in source to parse - * - * @see JSONParser - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - */ - public static Object parseWithException(Reader in) throws IOException, ParseException { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT); - } - - /** - * Parse JSON text into java object from the input source. - * - * @param input string to parse - - * @see JSONParser - * - * @throws ParseException if input in invalid - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - */ - public static Object parseWithException(String input) throws ParseException { - return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(input, defaultReader.DEFAULT); - } - - /** - * Parse input json as a mapTo class - * - * @param in source to parse - * @param mapTo destination type, mapTo can be a javabean - * - * @since 2.0 - * - * @return unserialized object of type mapTo - */ - public static T parseWithException(String in, Class mapTo) throws ParseException { - JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); - return p.parse(in, defaultReader.getMapper(mapTo)); - } - - /** - * Parse valid RFC4627 JSON text into java object from the input source. - * - * @param in source to parse - - * @see JSONParser - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - */ - public static Object parseStrict(Reader in) throws IOException, ParseException { - return new JSONParser(MODE_RFC4627).parse(in, defaultReader.DEFAULT); - } - - /** - * Parse valid RFC4627 JSON text into java object from the input source. - * - * @param s source to parse - * @see JSONParser - * - * @return Instance of the following: JSONObject, JSONArray, String, - * java.lang.Number, java.lang.Boolean, null - */ - public static Object parseStrict(String s) throws ParseException { - return new JSONParser(MODE_RFC4627).parse(s, defaultReader.DEFAULT); - } - - /** - * Check RFC4627 Json Syntax from input Reader - * - * @return if the input is valid - */ - public static boolean isValidJsonStrict(Reader in) throws IOException { - try { - new JSONParser(MODE_RFC4627).parse(in, FakeMapper.DEFAULT); - return true; - } catch (ParseException e) { - return false; - } - } - - /** - * check RFC4627 Json Syntax from input String - * - * @return if the input is valid - */ - public static boolean isValidJsonStrict(String s) { - try { - new JSONParser(MODE_RFC4627).parse(s, FakeMapper.DEFAULT); - return true; - } catch (ParseException e) { - return false; - } - } - - /** - * Check Json Syntax from input Reader - * - * @return if the input is valid - */ - public static boolean isValidJson(Reader in) throws IOException { - try { - new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, FakeMapper.DEFAULT); - return true; - } catch (ParseException e) { - return false; - } - } - - /** - * Check Json Syntax from input String - * - * @return if the input is valid - */ - public static boolean isValidJson(String s) { - try { - new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(s, FakeMapper.DEFAULT); - return true; - } catch (ParseException e) { - return false; - } - } - - /** - * Encode an object into JSON text and write it to out. - *

- * If this object is a Map or a List, and it's also a JSONStreamAware or a - * JSONAware, JSONStreamAware or JSONAware will be considered firstly. - *

- * - * @see JSONObject#writeJSON(Map, Appendable) - * @see JSONArray#writeJSONString(List, Appendable) - */ - public static void writeJSONString(Object value, Appendable out) throws IOException { - writeJSONString(value, out, COMPRESSION); - } - - /** - * Serialisation class Data - */ - public final static JsonWriter defaultWriter = new JsonWriter(); - /** - * deserialisation class Data - */ - public final static JsonReader defaultReader = new JsonReader(); - - /** - * Remap field from java to json, useful to avoid protected keyword in java class. - * - * @since 2.1.1 - * @param type type to alter - * @param jsonFieldName field name in json - * @param javaFieldName field name in java - */ - public static void remapField(Class type, String jsonFieldName, String javaFieldName) { - defaultReader.remapField(type, jsonFieldName, javaFieldName); - defaultWriter.remapField(type, javaFieldName, jsonFieldName); - } - - /** - * Register a serializer for a class. - */ - public static void registerWriter(Class cls, JsonWriterI writer) { - defaultWriter.registerWriter(writer, cls); - } - - /** - * register a deserializer for a class. - */ - public static void registerReader(Class type, JsonReaderI mapper) { - defaultReader.registerReader(type, mapper); - } - - /** - * Encode an object into JSON text and write it to out. - *

- * If this object is a Map or a List, and it's also a JSONStreamAware or a - * JSONAware, JSONStreamAware or JSONAware will be considered firstly. - *

- * - * @see JSONObject#writeJSON(Map, Appendable) - * @see JSONArray#writeJSONString(List, Appendable) - */ - @SuppressWarnings("unchecked") - public static void writeJSONString(Object value, Appendable out, JSONStyle compression) throws IOException { - if (value == null) { - out.append("null"); - return; - } - Class clz = value.getClass(); - @SuppressWarnings("rawtypes") - JsonWriterI w = defaultWriter.getWrite(clz); - if (w == null) { - if (clz.isArray()) - w = JsonWriter.arrayWriter; - else { - w = defaultWriter.getWriterByInterface(value.getClass()); - if (w == null) - w = JsonWriter.beansWriterASM; - // w = JsonWriter.beansWriter; - } - defaultWriter.registerWriter(w, clz); - } - w.writeJSONString(value, out, compression); - } - - /** - * Encode an object into JSON text and write it to out. - *

- * If this object is a Map or a List, and it's also a JSONStreamAware or a - * JSONAware, JSONStreamAware or JSONAware will be considered firstly. - *

- * - * @param value object to serialize - * - * @return json string - * - * @see JSONObject#writeJSON(Map, Appendable) - * @see JSONArray#writeJSONString(List, Appendable) - */ - public static String toJSONString(Object value) { - return toJSONString(value, COMPRESSION); - } - - /** - * Convert an object to JSON text. - *

- * If this object is a Map or a List, and it's also a JSONAware, JSONAware - * will be considered firstly. - *

- * DO NOT call this method from toJSONString() of a class that implements - * both JSONAware and Map or List with "this" as the parameter, use - * JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead. - * - * @param value to serialize - * @param compression serialisation options - * - * @see JSONObject#toJSONString(Map) - * @see JSONArray#toJSONString(List) - * - * @return JSON text, or "null" if value is null or it's an NaN or an INF - * number. - */ - public static String toJSONString(Object value, JSONStyle compression) { - StringBuilder sb = new StringBuilder(); - try { - writeJSONString(value, sb, compression); - } catch (IOException e) { - // can not append on a StringBuilder - } - return sb.toString(); - } - - public static String escape(String s) { - return escape(s, COMPRESSION); - } - - /** - * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters - * (U+0000 through U+001F). - * - * @param s string to escape - * @param compression compression options - * - * @return escaped string - */ - public static String escape(String s, JSONStyle compression) { - if (s == null) - return null; - StringBuilder sb = new StringBuilder(); - compression.escape(s, sb); - return sb.toString(); - } - - public static void escape(String s, Appendable ap) { - escape(s, ap, COMPRESSION); - } - - public static void escape(String s, Appendable ap, JSONStyle compression) { - if (s == null) - return; - compression.escape(s, ap); - } + /** Global default compression type */ + public static JSONStyle COMPRESSION = JSONStyle.NO_COMPRESS; + + /** + * Parse JSON text into java object from the input source. Please use parseWithException() if you + * don't want to ignore the exception. if you want strict input check use parseStrict() + * + * @see JSONParser#parse(Reader) + * @see #parseWithException(Reader) + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parse(InputStream in) { + try { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in); + } catch (Exception e) { + return null; + } + } + + /** + * Parse JSON text into java object from the input source. Please use parseWithException() if you + * don't want to ignore the exception. if you want strict input check use parseStrict() + * + * @see JSONParser#parse(Reader) + * @see #parseWithException(Reader) + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parse(byte[] in) { + try { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + *

mapTo can be a bean + * + * @since 2.0 + */ + public static T parse(InputStream in, Class mapTo) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, defaultReader.getMapper(mapTo)); + } catch (Exception e) { + return null; + } + } + + /** + * Parse JSON text into java object from the input source. Please use parseWithException() if you + * don't want to ignore the exception. if you want strict input check use parseStrict() + * + * @see JSONParser#parse(Reader) + * @see #parseWithException(Reader) + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parse(Reader in) { + try { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + *

mapTo can be a bean + * + * @since 2.0 + */ + public static T parse(byte[] in, Class mapTo) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, defaultReader.getMapper(mapTo)); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + *

mapTo can be a bean + * + * @since 2.0 + */ + public static T parse(Reader in, Class mapTo) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, defaultReader.getMapper(mapTo)); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + *

mapTo can be a bean + * + * @since 2.0 + */ + public static T parse(Reader in, T toUpdate) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, new UpdaterMapper(defaultReader, toUpdate)); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + * @since 2.0 + */ + protected static T parse(Reader in, JsonReaderI mapper) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, mapper); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + *

mapTo can be a bean + * + * @since 2.0 + */ + public static T parse(String in, Class mapTo) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, defaultReader.getMapper(mapTo)); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + *

mapTo can be a bean + * + * @since 2.0 + */ + public static T parse(InputStream in, T toUpdate) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, new UpdaterMapper(defaultReader, toUpdate)); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + *

mapTo can be a bean + * + * @since 2.0 + */ + public static T parse(String in, T toUpdate) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, new UpdaterMapper(defaultReader, toUpdate)); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + * @since 2.0 + */ + protected static T parse(byte[] in, JsonReaderI mapper) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, mapper); + } catch (Exception e) { + return null; + } + } + + /** + * Parse input json as a mapTo class + * + * @since 2.0 + */ + protected static T parse(String in, JsonReaderI mapper) { + try { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, mapper); + } catch (Exception e) { + return null; + } + } + + /** + * Parse JSON text into java object from the input source. Please use parseWithException() if you + * don't want to ignore the exception. if you want strict input check use parseStrict() + * + * @see JSONParser#parse(String) + * @see #parseWithException(String) + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parse(String s) { + try { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(s); + } catch (Exception e) { + return null; + } + } + + /** + * Parse Json input to a java Object keeping element order + * + * @param in json source + * @return a OrderedMap preserving field order. + * @since 1.0.6.1 + */ + public static Object parseKeepingOrder(Reader in) { + try { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT_ORDERED); + } catch (Exception e) { + return null; + } + } + + /** + * Parse Json input to a java Object keeping element order + * + * @param in json source + * @return a OrderedMap preserving field order.\ + * @since 1.0.6.1 + */ + public static Object parseKeepingOrder(String in) { + try { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT_ORDERED); + } catch (Exception e) { + return null; + } + } + + /** + * Reformat Json input keeping element order + * + * @param input text to parse + * @param style parse options + * @since 1.0.6.2 + * @return json string + */ + public static String compress(String input, JSONStyle style) { + try { + StringBuilder sb = new StringBuilder(); + new JSONParser(DEFAULT_PERMISSIVE_MODE) + .parse(input, new CompessorMapper(defaultReader, sb, style)); + return sb.toString(); + } catch (Exception e) { + return input; + } + } + + /** + * Compress Json input keeping element order + * + * @param input text to parse + * @since 1.0.6.1 + *

need to be rewrite in 2.0 + */ + public static String compress(String input) { + return compress(input, JSONStyle.MAX_COMPRESS); + } + + /** + * Compress Json input keeping element order + * + * @param input text to parse + * @since 1.0.6.1 + */ + public static String uncompress(String input) { + return compress(input, JSONStyle.NO_COMPRESS); + } + + /** + * Parse JSON text into java object from the input source. + * + * @param in source to parse + * @see JSONParser + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parseWithException(byte[] in) throws IOException, ParseException { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT); + } + + /** + * Parse JSON text into java object from the input source. + * + * @param in source to parse + * @see JSONParser + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parseWithException(InputStream in) throws IOException, ParseException { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT); + } + + /** + * Parse JSON text into java object from the input source. + * + * @param in source to parse + * @see JSONParser + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parseWithException(Reader in) throws IOException, ParseException { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, defaultReader.DEFAULT); + } + + /** + * Parse JSON text into java object from the input source. + * + * @param input string to parse + * @see JSONParser + * @throws ParseException if input in invalid + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parseWithException(String input) throws ParseException { + return new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(input, defaultReader.DEFAULT); + } + + /** + * Parse input json as a mapTo class + * + * @param in source to parse + * @param mapTo destination type, mapTo can be a javabean + * @since 2.0 + * @return unserialized object of type mapTo + */ + public static T parseWithException(String in, Class mapTo) throws ParseException { + JSONParser p = new JSONParser(DEFAULT_PERMISSIVE_MODE); + return p.parse(in, defaultReader.getMapper(mapTo)); + } + + /** + * Parse valid RFC4627 JSON text into java object from the input source. + * + * @param in source to parse + * @see JSONParser + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parseStrict(Reader in) throws IOException, ParseException { + return new JSONParser(MODE_RFC4627).parse(in, defaultReader.DEFAULT); + } + + /** + * Parse valid RFC4627 JSON text into java object from the input source. + * + * @param s source to parse + * @see JSONParser + * @return Instance of the following: JSONObject, JSONArray, String, java.lang.Number, + * java.lang.Boolean, null + */ + public static Object parseStrict(String s) throws ParseException { + return new JSONParser(MODE_RFC4627).parse(s, defaultReader.DEFAULT); + } + + /** + * Check RFC4627 Json Syntax from input Reader + * + * @return if the input is valid + */ + public static boolean isValidJsonStrict(Reader in) throws IOException { + try { + new JSONParser(MODE_RFC4627).parse(in, FakeMapper.DEFAULT); + return true; + } catch (ParseException e) { + return false; + } + } + + /** + * check RFC4627 Json Syntax from input String + * + * @return if the input is valid + */ + public static boolean isValidJsonStrict(String s) { + try { + new JSONParser(MODE_RFC4627).parse(s, FakeMapper.DEFAULT); + return true; + } catch (ParseException e) { + return false; + } + } + + /** + * Check Json Syntax from input Reader + * + * @return if the input is valid + */ + public static boolean isValidJson(Reader in) throws IOException { + try { + new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(in, FakeMapper.DEFAULT); + return true; + } catch (ParseException e) { + return false; + } + } + + /** + * Check Json Syntax from input String + * + * @return if the input is valid + */ + public static boolean isValidJson(String s) { + try { + new JSONParser(DEFAULT_PERMISSIVE_MODE).parse(s, FakeMapper.DEFAULT); + return true; + } catch (ParseException e) { + return false; + } + } + + /** + * Encode an object into JSON text and write it to out. + * + *

If this object is a Map or a List, and it's also a JSONStreamAware or a JSONAware, + * JSONStreamAware or JSONAware will be considered firstly. + * + *

+ * + * @see JSONObject#writeJSON(Map, Appendable) + * @see JSONArray#writeJSONString(List, Appendable) + */ + public static void writeJSONString(Object value, Appendable out) throws IOException { + writeJSONString(value, out, COMPRESSION); + } + + /** Serialisation class Data */ + public static final JsonWriter defaultWriter = new JsonWriter(); + + /** deserialisation class Data */ + public static final JsonReader defaultReader = new JsonReader(); + + /** + * Remap field from java to json, useful to avoid protected keyword in java class. + * + * @since 2.1.1 + * @param type type to alter + * @param jsonFieldName field name in json + * @param javaFieldName field name in java + */ + public static void remapField(Class type, String jsonFieldName, String javaFieldName) { + defaultReader.remapField(type, jsonFieldName, javaFieldName); + defaultWriter.remapField(type, javaFieldName, jsonFieldName); + } + + /** Register a serializer for a class. */ + public static void registerWriter(Class cls, JsonWriterI writer) { + defaultWriter.registerWriter(writer, cls); + } + + /** register a deserializer for a class. */ + public static void registerReader(Class type, JsonReaderI mapper) { + defaultReader.registerReader(type, mapper); + } + + /** + * Encode an object into JSON text and write it to out. + * + *

If this object is a Map or a List, and it's also a JSONStreamAware or a JSONAware, + * JSONStreamAware or JSONAware will be considered firstly. + * + * @see JSONObject#writeJSON(Map, Appendable) + * @see JSONArray#writeJSONString(List, Appendable) + */ + @SuppressWarnings("unchecked") + public static void writeJSONString(Object value, Appendable out, JSONStyle compression) + throws IOException { + if (value == null) { + out.append("null"); + return; + } + Class clz = value.getClass(); + @SuppressWarnings("rawtypes") + JsonWriterI w = defaultWriter.getWrite(clz); + if (w == null) { + if (clz.isArray()) w = JsonWriter.arrayWriter; + else { + w = defaultWriter.getWriterByInterface(value.getClass()); + if (w == null) w = JsonWriter.beansWriterASM; + // w = JsonWriter.beansWriter; + } + defaultWriter.registerWriter(w, clz); + } + w.writeJSONString(value, out, compression); + } + + /** + * Encode an object into JSON text and write it to out. + * + *

If this object is a Map or a List, and it's also a JSONStreamAware or a JSONAware, + * JSONStreamAware or JSONAware will be considered firstly. + * + *

+ * + * @param value object to serialize + * @return json string + * @see JSONObject#writeJSON(Map, Appendable) + * @see JSONArray#writeJSONString(List, Appendable) + */ + public static String toJSONString(Object value) { + return toJSONString(value, COMPRESSION); + } + + /** + * Convert an object to JSON text. + * + *

If this object is a Map or a List, and it's also a JSONAware, JSONAware will be considered + * firstly. + * + *

DO NOT call this method from toJSONString() of a class that implements both JSONAware and + * Map or List with "this" as the parameter, use JSONObject.toJSONString(Map) or + * JSONArray.toJSONString(List) instead. + * + * @param value to serialize + * @param compression serialisation options + * @see JSONObject#toJSONString(Map) + * @see JSONArray#toJSONString(List) + * @return JSON text, or "null" if value is null or it's an NaN or an INF number. + */ + public static String toJSONString(Object value, JSONStyle compression) { + StringBuilder sb = new StringBuilder(); + try { + writeJSONString(value, sb, compression); + } catch (IOException e) { + // can not append on a StringBuilder + } + return sb.toString(); + } + + public static String escape(String s) { + return escape(s, COMPRESSION); + } + + /** + * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F). + * + * @param s string to escape + * @param compression compression options + * @return escaped string + */ + public static String escape(String s, JSONStyle compression) { + if (s == null) return null; + StringBuilder sb = new StringBuilder(); + compression.escape(s, sb); + return sb.toString(); + } + + public static void escape(String s, Appendable ap) { + escape(s, ap, COMPRESSION); + } + + public static void escape(String s, Appendable ap, JSONStyle compression) { + if (s == null) return; + compression.escape(s, ap); + } } diff --git a/json-smart/src/main/java/net/minidev/json/JStylerObj.java b/json-smart/src/main/java/net/minidev/json/JStylerObj.java index b868571..b176465 100644 --- a/json-smart/src/main/java/net/minidev/json/JStylerObj.java +++ b/json-smart/src/main/java/net/minidev/json/JStylerObj.java @@ -19,311 +19,288 @@ /** * protected class used to stored Internal methods - * + * * @author Uriel Chemouni <uchemouni@gmail.com> */ class JStylerObj { - public final static MPSimple MP_SIMPLE = new MPSimple(); - public final static MPTrue MP_TRUE = new MPTrue(); - public final static MPAgressive MP_AGGRESIVE = new MPAgressive(); + public static final MPSimple MP_SIMPLE = new MPSimple(); + public static final MPTrue MP_TRUE = new MPTrue(); + public static final MPAgressive MP_AGGRESIVE = new MPAgressive(); + + public static final EscapeLT ESCAPE_LT = new EscapeLT(); + public static final Escape4Web ESCAPE4Web = new Escape4Web(); + + public static interface MustProtect { + public boolean mustBeProtect(String s); + } - public final static EscapeLT ESCAPE_LT = new EscapeLT(); - public final static Escape4Web ESCAPE4Web = new Escape4Web(); + private static class MPTrue implements MustProtect { + public boolean mustBeProtect(String s) { + return true; + } + } - public static interface MustProtect { - public boolean mustBeProtect(String s); - } + private static class MPSimple implements MustProtect { + /** + * can a String can be store without enclosing quotes. ie: should not contain any special json + * char + * + * @param s + * @return + */ + public boolean mustBeProtect(final String s) { + if (s == null) return false; + int len = s.length(); + if (len == 0) return true; + if (s.trim() != s) return true; - private static class MPTrue implements MustProtect { - public boolean mustBeProtect(String s) { - return true; - } - } + char ch = s.charAt(0); + if (ch >= '0' && ch <= '9' || ch == '-') return true; - private static class MPSimple implements MustProtect { - /** - * can a String can be store without enclosing quotes. ie: should not - * contain any special json char - * - * @param s - * @return - */ - public boolean mustBeProtect(final String s) { - if (s == null) - return false; - int len = s.length(); - if (len == 0) - return true; - if (s.trim() != s) - return true; + for (int i = 0; i < len; i++) { + ch = s.charAt(i); + if (isSpace(ch)) return true; + if (isSpecial(ch)) return true; + if (isSpecialChar(ch)) return true; + if (isUnicode(ch)) return true; + } + // keyword check + if (isKeyword(s)) return true; + return false; + } + } - char ch = s.charAt(0); - if (ch >= '0' && ch <= '9' || ch == '-') - return true; + private static class MPAgressive implements MustProtect { + public boolean mustBeProtect(final String s) { + if (s == null) return false; + int len = s.length(); + // protect empty String + if (len == 0) return true; - for (int i = 0; i < len; i++) { - ch = s.charAt(i); - if (isSpace(ch)) - return true; - if (isSpecial(ch)) - return true; - if (isSpecialChar(ch)) - return true; - if (isUnicode(ch)) - return true; - } - // keyword check - if (isKeyword(s)) - return true; - return false; - } - } + // protect trimable String + if (s.trim() != s) return true; - private static class MPAgressive implements MustProtect { - public boolean mustBeProtect(final String s) { - if (s == null) - return false; - int len = s.length(); - // protect empty String - if (len == 0) - return true; - - // protect trimable String - if (s.trim() != s) - return true; + // json special char + char ch = s.charAt(0); + if (isSpecial(ch) || isUnicode(ch)) return true; - // json special char - char ch = s.charAt(0); - if (isSpecial(ch) || isUnicode(ch)) - return true; + for (int i = 1; i < len; i++) { + ch = s.charAt(i); + if (isSpecialClose(ch) || isUnicode(ch)) return true; + } + // keyWord must be protect + if (isKeyword(s)) return true; + // Digit like text must be protect + ch = s.charAt(0); + // only test String if First Ch is a digit + if (ch >= '0' && ch <= '9' || ch == '-') { + int p = 1; + // skip first digits + for (; p < len; p++) { + ch = s.charAt(p); + if (ch < '0' || ch > '9') break; + } + // int/long + if (p == len) return true; + // Floating point + if (ch == '.') { + p++; + } + // Skip digits + for (; p < len; p++) { + ch = s.charAt(p); + if (ch < '0' || ch > '9') break; + } + if (p == len) return true; // can be read as an floating number + // Double + if (ch == 'E' || ch == 'e') { + p++; + if (p == len) // no power data not a digits + return false; + ch = s.charAt(p); + if (ch == '+' || ch == '-') { + p++; + ch = s.charAt(p); + } + } + if (p == len) // no power data => not a digit + return false; - for (int i = 1; i < len; i++) { - ch = s.charAt(i); - if (isSpecialClose(ch) || isUnicode(ch)) - return true; - } - // keyWord must be protect - if (isKeyword(s)) - return true; - // Digit like text must be protect - ch = s.charAt(0); - // only test String if First Ch is a digit - if (ch >= '0' && ch <= '9' || ch == '-') { - int p = 1; - // skip first digits - for (; p < len; p++) { - ch = s.charAt(p); - if (ch < '0' || ch > '9') - break; - } - // int/long - if (p == len) - return true; - // Floating point - if (ch == '.') { - p++; - } - // Skip digits - for (; p < len; p++) { - ch = s.charAt(p); - if (ch < '0' || ch > '9') - break; - } - if (p == len) - return true; // can be read as an floating number - // Double - if (ch == 'E' || ch == 'e') { - p++; - if (p == len) // no power data not a digits - return false; - ch = s.charAt(p); - if (ch == '+' || ch == '-') { - p++; - ch = s.charAt(p); - } - } - if (p == len) // no power data => not a digit - return false; - - for (; p < len; p++) { - ch = s.charAt(p); - if (ch < '0' || ch > '9') - break; - } - // floating point With power of data. - if (p == len) - return true; - return false; - } - return false; - } - } + for (; p < len; p++) { + ch = s.charAt(p); + if (ch < '0' || ch > '9') break; + } + // floating point With power of data. + if (p == len) return true; + return false; + } + return false; + } + } - public static boolean isSpace(char c) { - return (c == '\r' || c == '\n' || c == '\t' || c == ' '); - } + public static boolean isSpace(char c) { + return (c == '\r' || c == '\n' || c == '\t' || c == ' '); + } - public static boolean isSpecialChar(char c) { - return (c == '\b' || c == '\f' || c == '\n'); - } + public static boolean isSpecialChar(char c) { + return (c == '\b' || c == '\f' || c == '\n'); + } - public static boolean isSpecialOpen(char c) { - return (c == '{' || c == '[' || c == ',' || c == ':'); - } + public static boolean isSpecialOpen(char c) { + return (c == '{' || c == '[' || c == ',' || c == ':'); + } - public static boolean isSpecialClose(char c) { - return (c == '}' || c == ']' || c == ',' || c == ':'); - } + public static boolean isSpecialClose(char c) { + return (c == '}' || c == ']' || c == ',' || c == ':'); + } - public static boolean isSpecial(char c) { - return (c == '{' || c == '[' || c == ',' || c == '}' || c == ']' || c == ':' || c == '\'' || c == '"'); - } + public static boolean isSpecial(char c) { + return (c == '{' || c == '[' || c == ',' || c == '}' || c == ']' || c == ':' || c == '\'' + || c == '"'); + } - public static boolean isUnicode(char c) { - // ANSI control char - return ((c >= '\u0000' && c <= '\u001F') || - // DEL or unicode ctrl - (c >= '\u007F' && c <= '\u009F') || - // '\u00A0' No-breakable space ? - // En Quad .. more - (c >= '\u2000' && c <= '\u20FF')); - } + public static boolean isUnicode(char c) { + // ANSI control char + return ((c >= '\u0000' && c <= '\u001F') + || + // DEL or unicode ctrl + (c >= '\u007F' && c <= '\u009F') + || + // '\u00A0' No-breakable space ? + // En Quad .. more + (c >= '\u2000' && c <= '\u20FF')); + } - public static boolean isKeyword(String s) { - if (s.length() < 3) - return false; - char c = s.charAt(0); - if (c == 'n') - return s.equals("null"); - if (c == 't') - return s.equals("true"); - if (c == 'f') - return s.equals("false"); - if (c == 'N') - return s.equals("NaN"); - return false; - } + public static boolean isKeyword(String s) { + if (s.length() < 3) return false; + char c = s.charAt(0); + if (c == 'n') return s.equals("null"); + if (c == 't') return s.equals("true"); + if (c == 'f') return s.equals("false"); + if (c == 'N') return s.equals("NaN"); + return false; + } - public static interface StringProtector { - public void escape(String s, Appendable out); - } + public static interface StringProtector { + public void escape(String s, Appendable out); + } - private static class EscapeLT implements StringProtector { - /** - * Escape special chars form String except / - * - * @param s - * - Must not be null. - * @param out - */ - public void escape(String s, Appendable out) { - try { - int len = s.length(); - for (int i = 0; i < len; i++) { - char ch = s.charAt(i); - switch (ch) { - case '"': - out.append("\\\""); - break; - case '\\': - out.append("\\\\"); - break; - case '\b': - out.append("\\b"); - break; - case '\f': - out.append("\\f"); - break; - case '\n': - out.append("\\n"); - break; - case '\r': - out.append("\\r"); - break; - case '\t': - out.append("\\t"); - break; - default: - // Reference: - // http://www.unicode.org/versions/Unicode5.1.0/ - if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') - || (ch >= '\u2000' && ch <= '\u20FF')) { - out.append("\\u"); - String hex = "0123456789ABCDEF"; - out.append(hex.charAt(ch >> 12 & 0x000F)); - out.append(hex.charAt(ch >> 8 & 0x000F)); - out.append(hex.charAt(ch >> 4 & 0x000F)); - out.append(hex.charAt(ch >> 0 & 0x000F)); - } else { - out.append(ch); - } - } - } - } catch (IOException e) { - throw new RuntimeException("Impossible Exception"); - } - } - } + private static class EscapeLT implements StringProtector { + /** + * Escape special chars form String except / + * + * @param s - Must not be null. + * @param out + */ + public void escape(String s, Appendable out) { + try { + int len = s.length(); + for (int i = 0; i < len; i++) { + char ch = s.charAt(i); + switch (ch) { + case '"': + out.append("\\\""); + break; + case '\\': + out.append("\\\\"); + break; + case '\b': + out.append("\\b"); + break; + case '\f': + out.append("\\f"); + break; + case '\n': + out.append("\\n"); + break; + case '\r': + out.append("\\r"); + break; + case '\t': + out.append("\\t"); + break; + default: + // Reference: + // http://www.unicode.org/versions/Unicode5.1.0/ + if ((ch >= '\u0000' && ch <= '\u001F') + || (ch >= '\u007F' && ch <= '\u009F') + || (ch >= '\u2000' && ch <= '\u20FF')) { + out.append("\\u"); + String hex = "0123456789ABCDEF"; + out.append(hex.charAt(ch >> 12 & 0x000F)); + out.append(hex.charAt(ch >> 8 & 0x000F)); + out.append(hex.charAt(ch >> 4 & 0x000F)); + out.append(hex.charAt(ch >> 0 & 0x000F)); + } else { + out.append(ch); + } + } + } + } catch (IOException e) { + throw new RuntimeException("Impossible Exception"); + } + } + } - private static class Escape4Web implements StringProtector { + private static class Escape4Web implements StringProtector { - /** - * Escape special chars form String including / - * - * @param s - * - Must not be null. - * @param sb - */ - public void escape(String s, Appendable sb) { - try { - int len = s.length(); - for (int i = 0; i < len; i++) { - char ch = s.charAt(i); - switch (ch) { - case '"': - sb.append("\\\""); - break; - case '\\': - sb.append("\\\\"); - break; - case '\b': - sb.append("\\b"); - break; - case '\f': - sb.append("\\f"); - break; - case '\n': - sb.append("\\n"); - break; - case '\r': - sb.append("\\r"); - break; - case '\t': - sb.append("\\t"); - break; - case '/': - sb.append("\\/"); - break; - default: - // Reference: - // http://www.unicode.org/versions/Unicode5.1.0/ - if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') - || (ch >= '\u2000' && ch <= '\u20FF')) { - sb.append("\\u"); - String hex = "0123456789ABCDEF"; - sb.append(hex.charAt(ch >> 12 & 0x0F)); - sb.append(hex.charAt(ch >> 8 & 0x0F)); - sb.append(hex.charAt(ch >> 4 & 0x0F)); - sb.append(hex.charAt(ch >> 0 & 0x0F)); - } else { - sb.append(ch); - } - } - } - } catch (IOException e) { - throw new RuntimeException("Impossible Error"); - } - } - } + /** + * Escape special chars form String including / + * + * @param s - Must not be null. + * @param sb + */ + public void escape(String s, Appendable sb) { + try { + int len = s.length(); + for (int i = 0; i < len; i++) { + char ch = s.charAt(i); + switch (ch) { + case '"': + sb.append("\\\""); + break; + case '\\': + sb.append("\\\\"); + break; + case '\b': + sb.append("\\b"); + break; + case '\f': + sb.append("\\f"); + break; + case '\n': + sb.append("\\n"); + break; + case '\r': + sb.append("\\r"); + break; + case '\t': + sb.append("\\t"); + break; + case '/': + sb.append("\\/"); + break; + default: + // Reference: + // http://www.unicode.org/versions/Unicode5.1.0/ + if ((ch >= '\u0000' && ch <= '\u001F') + || (ch >= '\u007F' && ch <= '\u009F') + || (ch >= '\u2000' && ch <= '\u20FF')) { + sb.append("\\u"); + String hex = "0123456789ABCDEF"; + sb.append(hex.charAt(ch >> 12 & 0x0F)); + sb.append(hex.charAt(ch >> 8 & 0x0F)); + sb.append(hex.charAt(ch >> 4 & 0x0F)); + sb.append(hex.charAt(ch >> 0 & 0x0F)); + } else { + sb.append(ch); + } + } + } + } catch (IOException e) { + throw new RuntimeException("Impossible Error"); + } + } + } } diff --git a/json-smart/src/main/java/net/minidev/json/annotate/JsonIgnore.java b/json-smart/src/main/java/net/minidev/json/annotate/JsonIgnore.java index 77ad017..febc4b2 100644 --- a/json-smart/src/main/java/net/minidev/json/annotate/JsonIgnore.java +++ b/json-smart/src/main/java/net/minidev/json/annotate/JsonIgnore.java @@ -7,25 +7,19 @@ /** * block access to a field or to a getter or to a setter. - * - * If field and getter are annotate with @JsonIgnore the field will be Writable - * only - * - * - * If field and setter are annotate with @JsonIgnore the field will be Readable - * only - * - * - * If getter and setter are annotate with @JsonIgnore the field will be - * Read/Write using field if the field is public (default ) - * - * + * + *

If field and getter are annotate with @JsonIgnore the field will be Writable only + * + *

If field and setter are annotate with @JsonIgnore the field will be Readable only + * + *

If getter and setter are annotate with @JsonIgnore the field will be Read/Write using field if + * the field is public (default ) + * * @author uriel - * */ -@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD }) +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @JsonSmartAnnotation public @interface JsonIgnore { - boolean value() default true; + boolean value() default true; } diff --git a/json-smart/src/main/java/net/minidev/json/annotate/JsonSmartAnnotation.java b/json-smart/src/main/java/net/minidev/json/annotate/JsonSmartAnnotation.java index ba21ea9..03c7c96 100644 --- a/json-smart/src/main/java/net/minidev/json/annotate/JsonSmartAnnotation.java +++ b/json-smart/src/main/java/net/minidev/json/annotate/JsonSmartAnnotation.java @@ -7,13 +7,9 @@ /** * Jackson Annotation like - * - * @author uriel * + * @author uriel */ - -@Target({ ElementType.ANNOTATION_TYPE }) +@Target({ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) -public @interface JsonSmartAnnotation { - -} +public @interface JsonSmartAnnotation {} diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java index e33015f..bb93f06 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java @@ -18,278 +18,286 @@ import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; - import net.minidev.json.JSONValue; import net.minidev.json.writer.JsonReaderI; public class JSONParser { - /** - * allow simple quote as String quoting char - */ - public final static int ACCEPT_SIMPLE_QUOTE = 1; - /** - * allow non quoted test - */ - public final static int ACCEPT_NON_QUOTE = 2; - /** - * Parse NaN as Float.NaN - */ - public final static int ACCEPT_NAN = 4; - /** - * Ignore control char in input text. - */ - public final static int IGNORE_CONTROL_CHAR = 8; - /** - * Use int datatype to store number when it's possible. - * - * @since 1.0.7 - */ - public final static int USE_INTEGER_STORAGE = 16; - /** - * Throws exception on excessive 0 leading in digits - * - * @since 1.0.7 - */ - public final static int ACCEPT_LEADING_ZERO = 32; - /** - * Throws exception on useless comma in object and array - * - * @since 1.0.8 - */ - public final static int ACCEPT_USELESS_COMMA = 64; - /** - * Allow Json-smart to use Double or BigDecimal to store floating point - * value - * - * You may need to disable HI_PRECISION_FLOAT feature on 32bit to improve - * parsing performances. - * - * @since 1.0.9 - */ - public final static int USE_HI_PRECISION_FLOAT = 128; - /** - * If enabled json-smart will throws exception if datas are present after - * the end of the Json data. - * - * @since 1.0.9-2 - */ - public final static int ACCEPT_TAILLING_DATA = 256; - /** - * smart mode, fastest parsing mode. accept lots of non standard json syntax - * - * @since 2.0.1 - */ - public final static int ACCEPT_TAILLING_SPACE = 512; - /** - * smart mode, fastest parsing mode. accept lots of non standard json syntax - * - * @since 2.2.2 - */ - public final static int REJECT_127_CHAR = 1024; - - /** - * Use double if possible for big digits, if no precision lost is observed - * - * @since 2.4 - */ - public final static int BIG_DIGIT_UNRESTRICTED = 2048; - - /** - * If limit the max depth of json size - * - * @since 2.5 - */ - public static final int LIMIT_JSON_DEPTH = 4096; - - - /** - * smart mode, fastest parsing mode. accept lots of non standard json syntax - * - * @since 1.0.6 - */ - public final static int MODE_PERMISSIVE = -1; - /** - * strict RFC4627 mode. - * - * slower than PERMISSIVE MODE. - * - * @since 1.0.6 - */ - public final static int MODE_RFC4627 = USE_INTEGER_STORAGE | USE_HI_PRECISION_FLOAT | ACCEPT_TAILLING_SPACE | LIMIT_JSON_DEPTH; - /** - * Parse Object like json-simple - * - * Best for an iso-bug json-simple API port. - * - * @since 1.0.7 - */ - public final static int MODE_JSON_SIMPLE = ACCEPT_USELESS_COMMA | USE_HI_PRECISION_FLOAT | ACCEPT_TAILLING_DATA | ACCEPT_TAILLING_SPACE | REJECT_127_CHAR | BIG_DIGIT_UNRESTRICTED | LIMIT_JSON_DEPTH; - /** - * Strictest parsing mode - * - * @since 2.0.1 - */ - public final static int MODE_STRICTEST = USE_INTEGER_STORAGE | USE_HI_PRECISION_FLOAT | REJECT_127_CHAR | LIMIT_JSON_DEPTH; - /** - * Default json-smart processing mode - */ - public static int DEFAULT_PERMISSIVE_MODE = (System.getProperty("JSON_SMART_SIMPLE") != null) ? MODE_JSON_SIMPLE - : MODE_PERMISSIVE; - - /* - * internal fields - */ - private final int mode; - - private JSONParserInputStream pBinStream; - private JSONParserByteArray pBytes; - private JSONParserReader pStream; - private JSONParserString pString; - - private JSONParserReader getPStream() { - if (pStream == null) - pStream = new JSONParserReader(mode); - return pStream; - } - - /** - * cached constructor - * - * @return instance of JSONParserInputStream - */ - private JSONParserInputStream getPBinStream() { - if (pBinStream == null) - pBinStream = new JSONParserInputStream(mode); - return pBinStream; - } - - /** - * cached constructor - * - * @return instance of JSONParserString - */ - private JSONParserString getPString() { - if (pString == null) - pString = new JSONParserString(mode); - return pString; - } - - /** - * cached constructor - * - * @return instance of JSONParserByteArray - */ - private JSONParserByteArray getPBytes() { - if (pBytes == null) - pBytes = new JSONParserByteArray(mode); - return pBytes; - } - - /** - * @deprecated prefer usage of new JSONParser(JSONParser.MODE_*) - */ - public JSONParser() { - this.mode = DEFAULT_PERMISSIVE_MODE; - } - - public JSONParser(int permissifMode) { - this.mode = permissifMode; - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public Object parse(byte[] in) throws ParseException { - return getPBytes().parse(in); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(byte[] in, JsonReaderI mapper) throws ParseException { - return getPBytes().parse(in, mapper); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(byte[] in, Class mapTo) throws ParseException { - return getPBytes().parse(in, JSONValue.defaultReader.getMapper(mapTo)); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - * @throws UnsupportedEncodingException - */ - public Object parse(InputStream in) throws ParseException, UnsupportedEncodingException { - return getPBinStream().parse(in); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(InputStream in, JsonReaderI mapper) throws ParseException, UnsupportedEncodingException { - return getPBinStream().parse(in, mapper); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(InputStream in, Class mapTo) throws ParseException, UnsupportedEncodingException { - return getPBinStream().parse(in, JSONValue.defaultReader.getMapper(mapTo)); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public Object parse(Reader in) throws ParseException { - return getPStream().parse(in); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(Reader in, JsonReaderI mapper) throws ParseException { - return getPStream().parse(in, mapper); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(Reader in, Class mapTo) throws ParseException { - return getPStream().parse(in, JSONValue.defaultReader.getMapper(mapTo)); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public Object parse(String in) throws ParseException { - return getPString().parse(in); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(String in, JsonReaderI mapper) throws ParseException { - return getPString().parse(in, mapper); - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(String in, Class mapTo) throws ParseException { - return getPString().parse(in, JSONValue.defaultReader.getMapper(mapTo)); - } + /** allow simple quote as String quoting char */ + public static final int ACCEPT_SIMPLE_QUOTE = 1; + + /** allow non quoted test */ + public static final int ACCEPT_NON_QUOTE = 2; + + /** Parse NaN as Float.NaN */ + public static final int ACCEPT_NAN = 4; + + /** Ignore control char in input text. */ + public static final int IGNORE_CONTROL_CHAR = 8; + + /** + * Use int datatype to store number when it's possible. + * + * @since 1.0.7 + */ + public static final int USE_INTEGER_STORAGE = 16; + + /** + * Throws exception on excessive 0 leading in digits + * + * @since 1.0.7 + */ + public static final int ACCEPT_LEADING_ZERO = 32; + + /** + * Throws exception on useless comma in object and array + * + * @since 1.0.8 + */ + public static final int ACCEPT_USELESS_COMMA = 64; + + /** + * Allow Json-smart to use Double or BigDecimal to store floating point value + * + *

You may need to disable HI_PRECISION_FLOAT feature on 32bit to improve parsing performances. + * + * @since 1.0.9 + */ + public static final int USE_HI_PRECISION_FLOAT = 128; + + /** + * If enabled json-smart will throws exception if datas are present after the end of the Json + * data. + * + * @since 1.0.9-2 + */ + public static final int ACCEPT_TAILLING_DATA = 256; + + /** + * smart mode, fastest parsing mode. accept lots of non standard json syntax + * + * @since 2.0.1 + */ + public static final int ACCEPT_TAILLING_SPACE = 512; + + /** + * smart mode, fastest parsing mode. accept lots of non standard json syntax + * + * @since 2.2.2 + */ + public static final int REJECT_127_CHAR = 1024; + + /** + * Use double if possible for big digits, if no precision lost is observed + * + * @since 2.4 + */ + public static final int BIG_DIGIT_UNRESTRICTED = 2048; + + /** + * If limit the max depth of json size + * + * @since 2.5 + */ + public static final int LIMIT_JSON_DEPTH = 4096; + + /** + * smart mode, fastest parsing mode. accept lots of non standard json syntax + * + * @since 1.0.6 + */ + public static final int MODE_PERMISSIVE = -1; + + /** + * strict RFC4627 mode. + * + *

slower than PERMISSIVE MODE. + * + * @since 1.0.6 + */ + public static final int MODE_RFC4627 = + USE_INTEGER_STORAGE | USE_HI_PRECISION_FLOAT | ACCEPT_TAILLING_SPACE | LIMIT_JSON_DEPTH; + + /** + * Parse Object like json-simple + * + *

Best for an iso-bug json-simple API port. + * + * @since 1.0.7 + */ + public static final int MODE_JSON_SIMPLE = + ACCEPT_USELESS_COMMA + | USE_HI_PRECISION_FLOAT + | ACCEPT_TAILLING_DATA + | ACCEPT_TAILLING_SPACE + | REJECT_127_CHAR + | BIG_DIGIT_UNRESTRICTED + | LIMIT_JSON_DEPTH; + + /** + * Strictest parsing mode + * + * @since 2.0.1 + */ + public static final int MODE_STRICTEST = + USE_INTEGER_STORAGE | USE_HI_PRECISION_FLOAT | REJECT_127_CHAR | LIMIT_JSON_DEPTH; + + /** Default json-smart processing mode */ + public static int DEFAULT_PERMISSIVE_MODE = + (System.getProperty("JSON_SMART_SIMPLE") != null) ? MODE_JSON_SIMPLE : MODE_PERMISSIVE; + + /* + * internal fields + */ + private final int mode; + + private JSONParserInputStream pBinStream; + private JSONParserByteArray pBytes; + private JSONParserReader pStream; + private JSONParserString pString; + + private JSONParserReader getPStream() { + if (pStream == null) pStream = new JSONParserReader(mode); + return pStream; + } + + /** + * cached constructor + * + * @return instance of JSONParserInputStream + */ + private JSONParserInputStream getPBinStream() { + if (pBinStream == null) pBinStream = new JSONParserInputStream(mode); + return pBinStream; + } + + /** + * cached constructor + * + * @return instance of JSONParserString + */ + private JSONParserString getPString() { + if (pString == null) pString = new JSONParserString(mode); + return pString; + } + + /** + * cached constructor + * + * @return instance of JSONParserByteArray + */ + private JSONParserByteArray getPBytes() { + if (pBytes == null) pBytes = new JSONParserByteArray(mode); + return pBytes; + } + + /** + * @deprecated prefer usage of new JSONParser(JSONParser.MODE_*) + */ + public JSONParser() { + this.mode = DEFAULT_PERMISSIVE_MODE; + } + + public JSONParser(int permissifMode) { + this.mode = permissifMode; + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public Object parse(byte[] in) throws ParseException { + return getPBytes().parse(in); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(byte[] in, JsonReaderI mapper) throws ParseException { + return getPBytes().parse(in, mapper); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(byte[] in, Class mapTo) throws ParseException { + return getPBytes().parse(in, JSONValue.defaultReader.getMapper(mapTo)); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + * + * @throws UnsupportedEncodingException + */ + public Object parse(InputStream in) throws ParseException, UnsupportedEncodingException { + return getPBinStream().parse(in); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(InputStream in, JsonReaderI mapper) + throws ParseException, UnsupportedEncodingException { + return getPBinStream().parse(in, mapper); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(InputStream in, Class mapTo) + throws ParseException, UnsupportedEncodingException { + return getPBinStream().parse(in, JSONValue.defaultReader.getMapper(mapTo)); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public Object parse(Reader in) throws ParseException { + return getPStream().parse(in); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(Reader in, JsonReaderI mapper) throws ParseException { + return getPStream().parse(in, mapper); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(Reader in, Class mapTo) throws ParseException { + return getPStream().parse(in, JSONValue.defaultReader.getMapper(mapTo)); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public Object parse(String in) throws ParseException { + return getPString().parse(in); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(String in, JsonReaderI mapper) throws ParseException { + return getPString().parse(in, mapper); + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(String in, Class mapTo) throws ParseException { + return getPString().parse(in, JSONValue.defaultReader.getMapper(mapTo)); + } } diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java index f839e78..4fbb40f 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java @@ -17,816 +17,767 @@ */ import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_CHAR; import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_EOF; +import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_JSON_DEPTH; import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_LEADING_0; import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_TOKEN; import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_UNICODE; -import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_JSON_DEPTH; import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; - import net.minidev.json.writer.JsonReader; import net.minidev.json.writer.JsonReaderI; /** - * JSONParserBase is the common code between {@link JSONParserString} and - * {@link JSONParserReader} - * + * JSONParserBase is the common code between {@link JSONParserString} and {@link JSONParserReader} + * * @see JSONParserMemory * @see JSONParserStream - * * @author Uriel Chemouni <uchemouni@gmail.com> */ abstract class JSONParserBase { - protected char c; - /** - * hard coded maximal depth for JSON parsing - */ - public final static int MAX_DEPTH = 400; - protected int depth = 0; - - JsonReader base; - public final static byte EOI = 0x1A; - protected static final char MAX_STOP = 126; // '}' -> 125 - private String lastKey; - - protected static boolean[] stopAll = new boolean[MAX_STOP]; - protected static boolean[] stopArray = new boolean[MAX_STOP]; - protected static boolean[] stopKey = new boolean[MAX_STOP]; - protected static boolean[] stopValue = new boolean[MAX_STOP]; - protected static boolean[] stopX = new boolean[MAX_STOP]; - - static { - stopKey[':'] = stopKey[EOI] = true; - stopValue[','] = stopValue['}'] = stopValue[EOI] = true; - stopArray[','] = stopArray[']'] = stopArray[EOI] = true; - stopX[EOI] = true; - stopAll[','] = stopAll[':'] = true; - stopAll[']'] = stopAll['}'] = stopAll[EOI] = true; - } - - /* - * End of static declaration - */ - // - // - protected final MSB sb = new MSB(15); - protected Object xo; - protected String xs; - protected int pos; - - /* - * Parsing flags - */ - protected final boolean acceptLeadinZero; - protected final boolean acceptNaN; - protected final boolean acceptNonQuote; - protected final boolean acceptSimpleQuote; - protected final boolean acceptUselessComma; - protected final boolean checkTaillingData; - protected final boolean checkTaillingSpace; - protected final boolean ignoreControlChar; - protected final boolean useHiPrecisionFloat; - protected final boolean useIntegerStorage; - protected final boolean reject127; - protected final boolean unrestictBigDigit; - protected final boolean limitJsonDepth; - - public JSONParserBase(int permissiveMode) { - this.acceptNaN = (permissiveMode & JSONParser.ACCEPT_NAN) > 0; - this.acceptNonQuote = (permissiveMode & JSONParser.ACCEPT_NON_QUOTE) > 0; - this.acceptSimpleQuote = (permissiveMode & JSONParser.ACCEPT_SIMPLE_QUOTE) > 0; - this.ignoreControlChar = (permissiveMode & JSONParser.IGNORE_CONTROL_CHAR) > 0; - this.useIntegerStorage = (permissiveMode & JSONParser.USE_INTEGER_STORAGE) > 0; - this.acceptLeadinZero = (permissiveMode & JSONParser.ACCEPT_LEADING_ZERO) > 0; - this.acceptUselessComma = (permissiveMode & JSONParser.ACCEPT_USELESS_COMMA) > 0; - this.useHiPrecisionFloat = (permissiveMode & JSONParser.USE_HI_PRECISION_FLOAT) > 0; - this.checkTaillingData = (permissiveMode & (JSONParser.ACCEPT_TAILLING_DATA - | JSONParser.ACCEPT_TAILLING_SPACE)) != (JSONParser.ACCEPT_TAILLING_DATA - | JSONParser.ACCEPT_TAILLING_SPACE); - this.checkTaillingSpace = (permissiveMode & JSONParser.ACCEPT_TAILLING_SPACE) == 0; - this.reject127 = (permissiveMode & JSONParser.REJECT_127_CHAR) > 0; - this.unrestictBigDigit = (permissiveMode & JSONParser.BIG_DIGIT_UNRESTRICTED) > 0; - this.limitJsonDepth = (permissiveMode & JSONParser.LIMIT_JSON_DEPTH) > 0; - } - - public void checkControleChar() throws ParseException { - if (ignoreControlChar) - return; - int l = xs.length(); - for (int i = 0; i < l; i++) { - char c = xs.charAt(i); - if (c < 0) - continue; - if (c <= 31) - throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c); - if (c == 127) { - if (reject127) - throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c); - } - } - } - - public void checkLeadinZero() throws ParseException { - int len = xs.length(); - if (len == 1) - return; - if (len == 2) { - if (xs.equals("00")) - throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs); - return; - } - char c1 = xs.charAt(0); - char c2 = xs.charAt(1); - if (c1 == '-') { - char c3 = xs.charAt(2); - if (c2 == '0' && c3 >= '0' && c3 <= '9') - throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs); - return; - } - if (c1 == '0' && c2 >= '0' && c2 <= '9') - throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs); - } - - protected Number extractFloat() throws ParseException { - if (!acceptLeadinZero) - checkLeadinZero(); - - try { - if (!useHiPrecisionFloat) - return Float.parseFloat(xs); - - // follow JSonIJ parsing method - if (xs.length() > 18) { - // use extra CPU to check if the result can be return as double without - // precision lost - if (!unrestictBigDigit) { - double asDouble = Double.parseDouble(xs); - final String doubleStr = String.valueOf(asDouble); - // we need a compare `e` `E` `e+` `E+` - if (compareDoublePrecision(doubleStr, xs)) { - return asDouble; - } - } - return new BigDecimal(xs); - } - - return Double.parseDouble(xs); - - } catch (NumberFormatException e) { - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - } - } - - private boolean compareDoublePrecision(String convert, String origin) { - final char[] charArray = convert.toCharArray(); - final char[] originArray = origin.toCharArray(); - if (charArray.length > originArray.length) { - return false; - } - int j = 0; - for (int i = 0; i < charArray.length; i++) { - if (charArray[i] < '0' || charArray[i] > '9') { - if (originArray[j] >= '0' && originArray[j] <= '9') { - return false; - } else { - j++; - if (originArray[j] == '+') { - j++; - } - continue; - } - } - if (charArray[i] != originArray[j]) { - return false; - } - j++; - } - return j == originArray.length; - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray generated - * by a ContainerFactory - */ - protected T parse(JsonReaderI mapper) throws ParseException { - this.pos = -1; - T result; - try { - read(); - result = readFirst(mapper); - if (checkTaillingData) { - if (!checkTaillingSpace) - skipSpace(); - if (c != EOI) - throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c); - } - } catch (IOException e) { - throw new ParseException(pos, e); - } - xs = null; - xo = null; - return result; - } - - protected Number parseNumber(String s) throws ParseException { - // position - int p = 0; - // length - int l = s.length(); - // max position long base 10 length - int max = 19; - boolean neg; - - if (s.charAt(0) == '-') { - p++; - max++; - neg = true; - if (!acceptLeadinZero && l >= 3 && s.charAt(1) == '0') - throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s); - } else { - neg = false; - if (!acceptLeadinZero && l >= 2 && s.charAt(0) == '0') - throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s); - } - - boolean mustCheck; - if (l < max) { - max = l; - mustCheck = false; - } else if (l > max) { - return new BigInteger(s, 10); - } else { - max = l - 1; - mustCheck = true; - } - - long r = 0; - while (p < max) { - r = (r * 10L) + ('0' - s.charAt(p++)); - } - if (mustCheck) { - boolean isBig; - if (r > -922337203685477580L) { - isBig = false; - } else if (r < -922337203685477580L) { - isBig = true; - } else { - if (neg) - isBig = (s.charAt(p) > '8'); - else - isBig = (s.charAt(p) > '7'); - } - if (isBig) - return new BigInteger(s, 10); - r = r * 10L + ('0' - s.charAt(p)); - } - if (neg) { - if (this.useIntegerStorage && r >= Integer.MIN_VALUE) - return (int) r; - return r; - } - r = -r; - if (this.useIntegerStorage && r <= Integer.MAX_VALUE) - return (int) r; - return r; - } - - abstract protected void read() throws IOException; - - protected T readArray(JsonReaderI mapper) throws ParseException, IOException { - if (c != '[') - throw new RuntimeException("Internal Error"); - if (limitJsonDepth && ++this.depth > MAX_DEPTH) { - throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); - } - Object current = mapper.createArray(); - read(); - boolean needData = false; - // special case needData is false and can close is true - if (c == ',' && !acceptUselessComma) - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); - for (;;) { - switch (c) { - case ' ': - case '\r': - case '\n': - case '\t': - read(); - continue; - case ']': - if (needData && !acceptUselessComma) - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); - this.depth--; - read(); /* unstack */ - // - return mapper.convert(current); - case ':': - case '}': - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); - case ',': - if (needData && !acceptUselessComma) - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); - read(); - needData = true; - continue; - case EOI: - throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); - default: - mapper.addValue(current, readMain(mapper, stopArray)); - needData = false; - continue; - } - } - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray generated - * by a ContainerFactory - */ - protected T readFirst(JsonReaderI mapper) throws ParseException, IOException { - for (;;) { - switch (c) { - // skip spaces - case ' ': - case '\r': - case '\n': - case '\t': - read(); - continue; - // invalid state - case ':': - case '}': - case ']': - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); - // start object - case '{': - return readObject(mapper); - // start Array - case '[': - return readArray(mapper); - // start string - case '"': - case '\'': - readString(); - // - return mapper.convert(xs); - // string or null - case 'n': - readNQString(stopX); - if ("null".equals(xs)) { - // - return null; - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return mapper.convert(xs); - // string or false - case 'f': - readNQString(stopX); - if ("false".equals(xs)) { - // - return mapper.convert(Boolean.FALSE); - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return mapper.convert(xs); - // string or true - case 't': - readNQString(stopX); - if ("true".equals(xs)) { - // - return mapper.convert(Boolean.TRUE); - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return mapper.convert(xs); - // string or NaN - case 'N': - readNQString(stopX); - if (!acceptNaN) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - if ("NaN".equals(xs)) { - // - return mapper.convert(Float.valueOf(Float.NaN)); - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return mapper.convert(xs); - // digits - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - xo = readNumber(stopX); - // - return mapper.convert(xo); - default: - readNQString(stopX); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return mapper.convert(xs); - } - } - } - - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray generated - * by a ContainerFactory - */ - protected Object readMain(JsonReaderI mapper, boolean stop[]) throws ParseException, IOException { - for (;;) { - switch (c) { - // skip spaces - case ' ': - case '\r': - case '\n': - case '\t': - read(); - continue; - // invalid state - case ':': - case '}': - case ']': - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); - // start object - case '{': - return readObject(mapper.startObject(lastKey)); - // start Array - case '[': - return readArray(mapper.startArray(lastKey)); - // start string - case '"': - case '\'': - readString(); - // - return xs; - // string or null - case 'n': - readNQString(stop); - if ("null".equals(xs)) { - // - return null; - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return xs; - // string or false - case 'f': - readNQString(stop); - if ("false".equals(xs)) { - // - return Boolean.FALSE; - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return xs; - // string or true - case 't': - readNQString(stop); - if ("true".equals(xs)) { - // - return Boolean.TRUE; - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return xs; - // string or NaN - case 'N': - readNQString(stop); - if (!acceptNaN) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - if ("NaN".equals(xs)) { - // - return Float.valueOf(Float.NaN); - } - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return xs; - // digits - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - // - // - return readNumber(stop); - default: - readNQString(stop); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - // - return xs; - } - } - } - - abstract protected void readNoEnd() throws ParseException, IOException; - - abstract protected void readNQString(boolean[] stop) throws IOException; - - abstract protected Object readNumber(boolean[] stop) throws ParseException, IOException; - - protected T readObject(JsonReaderI mapper) throws ParseException, IOException { - // - if (c != '{') - throw new RuntimeException("Internal Error"); - if (limitJsonDepth && ++this.depth > MAX_DEPTH) { - throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); - } - Object current = mapper.createObject(); - boolean needData = false; - boolean acceptData = true; - for (;;) { - read(); - switch (c) { - case ' ': - case '\r': - case '\t': - case '\n': - continue; - case ':': - case ']': - case '[': - case '{': - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); - case '}': - if (needData && !acceptUselessComma) - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); - this.depth--; - read(); /* unstack */ - // - return mapper.convert(current); - case ',': - if (needData && !acceptUselessComma) - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); - acceptData = needData = true; - continue; - case '"': - case '\'': - default: - // int keyStart = pos; - if (c == '\"' || c == '\'') { - readString(); - } else { - readNQString(stopKey); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - } - String key = xs; - if (!acceptData) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, key); - - // Skip spaces - skipSpace(); - - if (c != ':') { - if (c == EOI) - throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null); - throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, c); - } - readNoEnd(); /* skip : */ - lastKey = key; - Object value = readMain(mapper, stopValue); - mapper.setValue(current, key, value); - lastKey = null; - - // Object duplicate = obj.put(key, readMain(stopValue)); - // if (duplicate != null) - // throw new ParseException(keyStart, ERROR_UNEXPECTED_DUPLICATE_KEY, key); - // handler.endObjectEntry(); - // should loop skipping read step - skipSpace(); - if (c == '}') { - this.depth--; - read(); /* unstack */ - // - return mapper.convert(current); - } - if (c == EOI) // Fixed on 18/10/2011 reported by vladimir - throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null); - // if c==, continue - if (c == ',') - acceptData = needData = true; - else - throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c); - // acceptData = needData = false; - } - } - } - - /** - * store and read - */ - abstract void readS() throws IOException; - - abstract protected void readString() throws ParseException, IOException; - - protected void readString2() throws ParseException, IOException { - /* assert (c == '\"' || c == '\'') */ - char sep = c; - for (;;) { - read(); - switch (c) { - case EOI: - throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null); - case '"': - case '\'': - if (sep == c) { - read(); - xs = sb.toString(); - return; - } - sb.append(c); - break; - case '\\': - read(); - switch (c) { - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'r': - sb.append('\r'); - break; - case 'f': - sb.append('\f'); - break; - case 'b': - sb.append('\b'); - break; - case '\\': - sb.append('\\'); - break; - case '/': - sb.append('/'); - break; - case '\'': - sb.append('\''); - break; - case '"': - sb.append('"'); - break; - case 'u': - sb.append(readUnicode(4)); - break; - case 'x': - sb.append(readUnicode(2)); - break; - default: - break; - } - break; - case '\0': // end of string - case (char) 1: // Start of heading - case (char) 2: // Start of text - case (char) 3: // End of text - case (char) 4: // End of transmission - case (char) 5: // Enquiry - case (char) 6: // Acknowledge - case (char) 7: // Bell - case '\b': // 8: backSpase - case '\t': // 9: horizontal tab - case '\n': // 10: new line - case (char) 11: // Vertical tab - case '\f': // 12: form feed - case '\r': // 13: return carriage - case (char) 14: // Shift Out, alternate character set - case (char) 15: // Shift In, resume defaultn character set - case (char) 16: // Data link escape - case (char) 17: // XON, with XOFF to pause listings; - case (char) 18: // Device control 2, block-mode flow control - case (char) 19: // XOFF, with XON is TERM=18 flow control - case (char) 20: // Device control 4 - case (char) 21: // Negative acknowledge - case (char) 22: // Synchronous idle - case (char) 23: // End transmission block, not the same as EOT - case (char) 24: // Cancel line, MPE echoes !!! - case (char) 25: // End of medium, Control-Y interrupt - // case (char) 26: // Substitute == EOI - case (char) 27: // escape - case (char) 28: // File Separator - case (char) 29: // Group Separator - case (char) 30: // Record Separator - case (char) 31: // Unit Separator - if (ignoreControlChar) - continue; - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); - case (char) 127: // del - if (ignoreControlChar) - continue; - if (reject127) - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); - default: - sb.append(c); - } - } - } - - protected char readUnicode(int totalChars) throws ParseException, IOException { - int value = 0; - for (int i = 0; i < totalChars; i++) { - value = value * 16; - read(); - if (c <= '9' && c >= '0') - value += c - '0'; - else if (c <= 'F' && c >= 'A') - value += (c - 'A') + 10; - else if (c >= 'a' && c <= 'f') - value += (c - 'a') + 10; - else if (c == EOI) - throw new ParseException(pos, ERROR_UNEXPECTED_EOF, "EOF"); - else - throw new ParseException(pos, ERROR_UNEXPECTED_UNICODE, c); - } - return (char) value; - } - - protected void skipDigits() throws IOException { - for (;;) { - if (c < '0' || c > '9') - return; - readS(); - } - } - - protected void skipNQString(boolean[] stop) throws IOException { - for (;;) { - if ((c == EOI) || (c >= 0 && c < MAX_STOP && stop[c])) - return; - readS(); - } - } - - protected void skipSpace() throws IOException { - for (;;) { - if (c > ' ' || c == EOI) - return; - readS(); - } - } - - public static class MSB { - char b[]; - int p; - - public MSB(int size) { - b = new char[size]; - p = -1; - } - - public void append(char c) { - p++; - if (b.length <= p) { - char[] t = new char[b.length * 2 + 1]; - System.arraycopy(b, 0, t, 0, b.length); - b = t; - } - b[p] = c; - } - - public void append(int c) { - p++; - if (b.length <= p) { - char[] t = new char[b.length * 2 + 1]; - System.arraycopy(b, 0, t, 0, b.length); - b = t; - } - b[p] = (char) c; - } - - public String toString() { - return new String(b, 0, p + 1); - } - - public void clear() { - p = -1; - } - } + protected char c; + + /** hard coded maximal depth for JSON parsing */ + public static final int MAX_DEPTH = 400; + + protected int depth = 0; + + JsonReader base; + public static final byte EOI = 0x1A; + protected static final char MAX_STOP = 126; // '}' -> 125 + private String lastKey; + + protected static boolean[] stopAll = new boolean[MAX_STOP]; + protected static boolean[] stopArray = new boolean[MAX_STOP]; + protected static boolean[] stopKey = new boolean[MAX_STOP]; + protected static boolean[] stopValue = new boolean[MAX_STOP]; + protected static boolean[] stopX = new boolean[MAX_STOP]; + + static { + stopKey[':'] = stopKey[EOI] = true; + stopValue[','] = stopValue['}'] = stopValue[EOI] = true; + stopArray[','] = stopArray[']'] = stopArray[EOI] = true; + stopX[EOI] = true; + stopAll[','] = stopAll[':'] = true; + stopAll[']'] = stopAll['}'] = stopAll[EOI] = true; + } + + /* + * End of static declaration + */ + // + // + protected final MSB sb = new MSB(15); + protected Object xo; + protected String xs; + protected int pos; + + /* + * Parsing flags + */ + protected final boolean acceptLeadinZero; + protected final boolean acceptNaN; + protected final boolean acceptNonQuote; + protected final boolean acceptSimpleQuote; + protected final boolean acceptUselessComma; + protected final boolean checkTaillingData; + protected final boolean checkTaillingSpace; + protected final boolean ignoreControlChar; + protected final boolean useHiPrecisionFloat; + protected final boolean useIntegerStorage; + protected final boolean reject127; + protected final boolean unrestictBigDigit; + protected final boolean limitJsonDepth; + + public JSONParserBase(int permissiveMode) { + this.acceptNaN = (permissiveMode & JSONParser.ACCEPT_NAN) > 0; + this.acceptNonQuote = (permissiveMode & JSONParser.ACCEPT_NON_QUOTE) > 0; + this.acceptSimpleQuote = (permissiveMode & JSONParser.ACCEPT_SIMPLE_QUOTE) > 0; + this.ignoreControlChar = (permissiveMode & JSONParser.IGNORE_CONTROL_CHAR) > 0; + this.useIntegerStorage = (permissiveMode & JSONParser.USE_INTEGER_STORAGE) > 0; + this.acceptLeadinZero = (permissiveMode & JSONParser.ACCEPT_LEADING_ZERO) > 0; + this.acceptUselessComma = (permissiveMode & JSONParser.ACCEPT_USELESS_COMMA) > 0; + this.useHiPrecisionFloat = (permissiveMode & JSONParser.USE_HI_PRECISION_FLOAT) > 0; + this.checkTaillingData = + (permissiveMode & (JSONParser.ACCEPT_TAILLING_DATA | JSONParser.ACCEPT_TAILLING_SPACE)) + != (JSONParser.ACCEPT_TAILLING_DATA | JSONParser.ACCEPT_TAILLING_SPACE); + this.checkTaillingSpace = (permissiveMode & JSONParser.ACCEPT_TAILLING_SPACE) == 0; + this.reject127 = (permissiveMode & JSONParser.REJECT_127_CHAR) > 0; + this.unrestictBigDigit = (permissiveMode & JSONParser.BIG_DIGIT_UNRESTRICTED) > 0; + this.limitJsonDepth = (permissiveMode & JSONParser.LIMIT_JSON_DEPTH) > 0; + } + + public void checkControleChar() throws ParseException { + if (ignoreControlChar) return; + int l = xs.length(); + for (int i = 0; i < l; i++) { + char c = xs.charAt(i); + if (c < 0) continue; + if (c <= 31) throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c); + if (c == 127) { + if (reject127) throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c); + } + } + } + + public void checkLeadinZero() throws ParseException { + int len = xs.length(); + if (len == 1) return; + if (len == 2) { + if (xs.equals("00")) throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs); + return; + } + char c1 = xs.charAt(0); + char c2 = xs.charAt(1); + if (c1 == '-') { + char c3 = xs.charAt(2); + if (c2 == '0' && c3 >= '0' && c3 <= '9') + throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs); + return; + } + if (c1 == '0' && c2 >= '0' && c2 <= '9') + throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs); + } + + protected Number extractFloat() throws ParseException { + if (!acceptLeadinZero) checkLeadinZero(); + + try { + if (!useHiPrecisionFloat) return Float.parseFloat(xs); + + // follow JSonIJ parsing method + if (xs.length() > 18) { + // use extra CPU to check if the result can be return as double without + // precision lost + if (!unrestictBigDigit) { + double asDouble = Double.parseDouble(xs); + final String doubleStr = String.valueOf(asDouble); + // we need a compare `e` `E` `e+` `E+` + if (compareDoublePrecision(doubleStr, xs)) { + return asDouble; + } + } + return new BigDecimal(xs); + } + + return Double.parseDouble(xs); + + } catch (NumberFormatException e) { + throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + } + } + + private boolean compareDoublePrecision(String convert, String origin) { + final char[] charArray = convert.toCharArray(); + final char[] originArray = origin.toCharArray(); + if (charArray.length > originArray.length) { + return false; + } + int j = 0; + for (int i = 0; i < charArray.length; i++) { + if (charArray[i] < '0' || charArray[i] > '9') { + if (originArray[j] >= '0' && originArray[j] <= '9') { + return false; + } else { + j++; + if (originArray[j] == '+') { + j++; + } + continue; + } + } + if (charArray[i] != originArray[j]) { + return false; + } + j++; + } + return j == originArray.length; + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + protected T parse(JsonReaderI mapper) throws ParseException { + this.pos = -1; + T result; + try { + read(); + result = readFirst(mapper); + if (checkTaillingData) { + if (!checkTaillingSpace) skipSpace(); + if (c != EOI) throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c); + } + } catch (IOException e) { + throw new ParseException(pos, e); + } + xs = null; + xo = null; + return result; + } + + protected Number parseNumber(String s) throws ParseException { + // position + int p = 0; + // length + int l = s.length(); + // max position long base 10 length + int max = 19; + boolean neg; + + if (s.charAt(0) == '-') { + p++; + max++; + neg = true; + if (!acceptLeadinZero && l >= 3 && s.charAt(1) == '0') + throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s); + } else { + neg = false; + if (!acceptLeadinZero && l >= 2 && s.charAt(0) == '0') + throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s); + } + + boolean mustCheck; + if (l < max) { + max = l; + mustCheck = false; + } else if (l > max) { + return new BigInteger(s, 10); + } else { + max = l - 1; + mustCheck = true; + } + + long r = 0; + while (p < max) { + r = (r * 10L) + ('0' - s.charAt(p++)); + } + if (mustCheck) { + boolean isBig; + if (r > -922337203685477580L) { + isBig = false; + } else if (r < -922337203685477580L) { + isBig = true; + } else { + if (neg) isBig = (s.charAt(p) > '8'); + else isBig = (s.charAt(p) > '7'); + } + if (isBig) return new BigInteger(s, 10); + r = r * 10L + ('0' - s.charAt(p)); + } + if (neg) { + if (this.useIntegerStorage && r >= Integer.MIN_VALUE) return (int) r; + return r; + } + r = -r; + if (this.useIntegerStorage && r <= Integer.MAX_VALUE) return (int) r; + return r; + } + + protected abstract void read() throws IOException; + + protected T readArray(JsonReaderI mapper) throws ParseException, IOException { + if (c != '[') throw new RuntimeException("Internal Error"); + if (limitJsonDepth && ++this.depth > MAX_DEPTH) { + throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); + } + Object current = mapper.createArray(); + read(); + boolean needData = false; + // special case needData is false and can close is true + if (c == ',' && !acceptUselessComma) + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); + for (; ; ) { + switch (c) { + case ' ': + case '\r': + case '\n': + case '\t': + read(); + continue; + case ']': + if (needData && !acceptUselessComma) + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); + this.depth--; + read(); /* unstack */ + // + return mapper.convert(current); + case ':': + case '}': + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); + case ',': + if (needData && !acceptUselessComma) + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); + read(); + needData = true; + continue; + case EOI: + throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); + default: + mapper.addValue(current, readMain(mapper, stopArray)); + needData = false; + continue; + } + } + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + protected T readFirst(JsonReaderI mapper) throws ParseException, IOException { + for (; ; ) { + switch (c) { + // skip spaces + case ' ': + case '\r': + case '\n': + case '\t': + read(); + continue; + // invalid state + case ':': + case '}': + case ']': + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); + // start object + case '{': + return readObject(mapper); + // start Array + case '[': + return readArray(mapper); + // start string + case '"': + case '\'': + readString(); + // + return mapper.convert(xs); + // string or null + case 'n': + readNQString(stopX); + if ("null".equals(xs)) { + // + return null; + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return mapper.convert(xs); + // string or false + case 'f': + readNQString(stopX); + if ("false".equals(xs)) { + // + return mapper.convert(Boolean.FALSE); + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return mapper.convert(xs); + // string or true + case 't': + readNQString(stopX); + if ("true".equals(xs)) { + // + return mapper.convert(Boolean.TRUE); + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return mapper.convert(xs); + // string or NaN + case 'N': + readNQString(stopX); + if (!acceptNaN) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + if ("NaN".equals(xs)) { + // + return mapper.convert(Float.valueOf(Float.NaN)); + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return mapper.convert(xs); + // digits + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + xo = readNumber(stopX); + // + return mapper.convert(xo); + default: + readNQString(stopX); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return mapper.convert(xs); + } + } + } + + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + protected Object readMain(JsonReaderI mapper, boolean stop[]) + throws ParseException, IOException { + for (; ; ) { + switch (c) { + // skip spaces + case ' ': + case '\r': + case '\n': + case '\t': + read(); + continue; + // invalid state + case ':': + case '}': + case ']': + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); + // start object + case '{': + return readObject(mapper.startObject(lastKey)); + // start Array + case '[': + return readArray(mapper.startArray(lastKey)); + // start string + case '"': + case '\'': + readString(); + // + return xs; + // string or null + case 'n': + readNQString(stop); + if ("null".equals(xs)) { + // + return null; + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return xs; + // string or false + case 'f': + readNQString(stop); + if ("false".equals(xs)) { + // + return Boolean.FALSE; + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return xs; + // string or true + case 't': + readNQString(stop); + if ("true".equals(xs)) { + // + return Boolean.TRUE; + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return xs; + // string or NaN + case 'N': + readNQString(stop); + if (!acceptNaN) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + if ("NaN".equals(xs)) { + // + return Float.valueOf(Float.NaN); + } + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return xs; + // digits + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + // + // + return readNumber(stop); + default: + readNQString(stop); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + // + return xs; + } + } + } + + protected abstract void readNoEnd() throws ParseException, IOException; + + protected abstract void readNQString(boolean[] stop) throws IOException; + + protected abstract Object readNumber(boolean[] stop) throws ParseException, IOException; + + protected T readObject(JsonReaderI mapper) throws ParseException, IOException { + // + if (c != '{') throw new RuntimeException("Internal Error"); + if (limitJsonDepth && ++this.depth > MAX_DEPTH) { + throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); + } + Object current = mapper.createObject(); + boolean needData = false; + boolean acceptData = true; + for (; ; ) { + read(); + switch (c) { + case ' ': + case '\r': + case '\t': + case '\n': + continue; + case ':': + case ']': + case '[': + case '{': + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); + case '}': + if (needData && !acceptUselessComma) + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); + this.depth--; + read(); /* unstack */ + // + return mapper.convert(current); + case ',': + if (needData && !acceptUselessComma) + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); + acceptData = needData = true; + continue; + case '"': + case '\'': + default: + // int keyStart = pos; + if (c == '\"' || c == '\'') { + readString(); + } else { + readNQString(stopKey); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + } + String key = xs; + if (!acceptData) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, key); + + // Skip spaces + skipSpace(); + + if (c != ':') { + if (c == EOI) throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null); + throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, c); + } + readNoEnd(); /* skip : */ + lastKey = key; + Object value = readMain(mapper, stopValue); + mapper.setValue(current, key, value); + lastKey = null; + + // Object duplicate = obj.put(key, readMain(stopValue)); + // if (duplicate != null) + // throw new ParseException(keyStart, ERROR_UNEXPECTED_DUPLICATE_KEY, key); + // handler.endObjectEntry(); + // should loop skipping read step + skipSpace(); + if (c == '}') { + this.depth--; + read(); /* unstack */ + // + return mapper.convert(current); + } + if (c == EOI) // Fixed on 18/10/2011 reported by vladimir + throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null); + // if c==, continue + if (c == ',') acceptData = needData = true; + else throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c); + // acceptData = needData = false; + } + } + } + + /** store and read */ + abstract void readS() throws IOException; + + protected abstract void readString() throws ParseException, IOException; + + protected void readString2() throws ParseException, IOException { + /* assert (c == '\"' || c == '\'') */ + char sep = c; + for (; ; ) { + read(); + switch (c) { + case EOI: + throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null); + case '"': + case '\'': + if (sep == c) { + read(); + xs = sb.toString(); + return; + } + sb.append(c); + break; + case '\\': + read(); + switch (c) { + case 't': + sb.append('\t'); + break; + case 'n': + sb.append('\n'); + break; + case 'r': + sb.append('\r'); + break; + case 'f': + sb.append('\f'); + break; + case 'b': + sb.append('\b'); + break; + case '\\': + sb.append('\\'); + break; + case '/': + sb.append('/'); + break; + case '\'': + sb.append('\''); + break; + case '"': + sb.append('"'); + break; + case 'u': + sb.append(readUnicode(4)); + break; + case 'x': + sb.append(readUnicode(2)); + break; + default: + break; + } + break; + case '\0': // end of string + case (char) 1: // Start of heading + case (char) 2: // Start of text + case (char) 3: // End of text + case (char) 4: // End of transmission + case (char) 5: // Enquiry + case (char) 6: // Acknowledge + case (char) 7: // Bell + case '\b': // 8: backSpase + case '\t': // 9: horizontal tab + case '\n': // 10: new line + case (char) 11: // Vertical tab + case '\f': // 12: form feed + case '\r': // 13: return carriage + case (char) 14: // Shift Out, alternate character set + case (char) 15: // Shift In, resume defaultn character set + case (char) 16: // Data link escape + case (char) 17: // XON, with XOFF to pause listings; + case (char) 18: // Device control 2, block-mode flow control + case (char) 19: // XOFF, with XON is TERM=18 flow control + case (char) 20: // Device control 4 + case (char) 21: // Negative acknowledge + case (char) 22: // Synchronous idle + case (char) 23: // End transmission block, not the same as EOT + case (char) 24: // Cancel line, MPE echoes !!! + case (char) 25: // End of medium, Control-Y interrupt + // case (char) 26: // Substitute == EOI + case (char) 27: // escape + case (char) 28: // File Separator + case (char) 29: // Group Separator + case (char) 30: // Record Separator + case (char) 31: // Unit Separator + if (ignoreControlChar) continue; + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); + case (char) 127: // del + if (ignoreControlChar) continue; + if (reject127) throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); + default: + sb.append(c); + } + } + } + + protected char readUnicode(int totalChars) throws ParseException, IOException { + int value = 0; + for (int i = 0; i < totalChars; i++) { + value = value * 16; + read(); + if (c <= '9' && c >= '0') value += c - '0'; + else if (c <= 'F' && c >= 'A') value += (c - 'A') + 10; + else if (c >= 'a' && c <= 'f') value += (c - 'a') + 10; + else if (c == EOI) throw new ParseException(pos, ERROR_UNEXPECTED_EOF, "EOF"); + else throw new ParseException(pos, ERROR_UNEXPECTED_UNICODE, c); + } + return (char) value; + } + + protected void skipDigits() throws IOException { + for (; ; ) { + if (c < '0' || c > '9') return; + readS(); + } + } + + protected void skipNQString(boolean[] stop) throws IOException { + for (; ; ) { + if ((c == EOI) || (c >= 0 && c < MAX_STOP && stop[c])) return; + readS(); + } + } + + protected void skipSpace() throws IOException { + for (; ; ) { + if (c > ' ' || c == EOI) return; + readS(); + } + } + + public static class MSB { + char b[]; + int p; + + public MSB(int size) { + b = new char[size]; + p = -1; + } + + public void append(char c) { + p++; + if (b.length <= p) { + char[] t = new char[b.length * 2 + 1]; + System.arraycopy(b, 0, t, 0, b.length); + b = t; + } + b[p] = c; + } + + public void append(int c) { + p++; + if (b.length <= p) { + char[] t = new char[b.length * 2 + 1]; + System.arraycopy(b, 0, t, 0, b.length); + b = t; + } + b[p] = (char) c; + } + + public String toString() { + return new String(b, 0, p + 1); + } + + public void clear() { + p = -1; + } + } } diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserByteArray.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserByteArray.java index 47f0fd7..ea8035d 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserByteArray.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserByteArray.java @@ -16,99 +16,87 @@ * limitations under the License. */ import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_EOF; -import net.minidev.json.JSONValue; -import net.minidev.json.writer.JsonReaderI; - import java.nio.charset.StandardCharsets; +import net.minidev.json.JSONValue; +import net.minidev.json.writer.JsonReaderI; /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * + * * @author Uriel Chemouni <uchemouni@gmail.com> */ class JSONParserByteArray extends JSONParserMemory { - private byte[] in; + private byte[] in; - public JSONParserByteArray(int permissiveMode) { - super(permissiveMode); - } + public JSONParserByteArray(int permissiveMode) { + super(permissiveMode); + } - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public Object parse(byte[] in) throws ParseException { - return parse(in, JSONValue.defaultReader.DEFAULT); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public Object parse(byte[] in) throws ParseException { + return parse(in, JSONValue.defaultReader.DEFAULT); + } - // - // - // - // - // - // - // + // + // + // + // + // + // + // - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(byte[] in, JsonReaderI mapper) throws ParseException { - this.base = mapper.base; - this.in = in; - this.len = in.length; - return parse(mapper); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(byte[] in, JsonReaderI mapper) throws ParseException { + this.base = mapper.base; + this.in = in; + this.len = in.length; + return parse(mapper); + } - protected void extractString(int beginIndex, int endIndex) { - xs = new String(in, beginIndex, endIndex - beginIndex, StandardCharsets.UTF_8); - } + protected void extractString(int beginIndex, int endIndex) { + xs = new String(in, beginIndex, endIndex - beginIndex, StandardCharsets.UTF_8); + } - protected void extractStringTrim(int start, int stop) { - byte[] val = this.in; /* avoid getfield opcode */ + protected void extractStringTrim(int start, int stop) { + byte[] val = this.in; /* avoid getfield opcode */ - while ((start < stop) && (val[start] <= ' ')) { - start++; - } - while ((start < stop) && (val[stop - 1] <= ' ')) { - stop--; - } - xs = new String(in, start, stop - start, StandardCharsets.UTF_8); - } + while ((start < stop) && (val[start] <= ' ')) { + start++; + } + while ((start < stop) && (val[stop - 1] <= ' ')) { + stop--; + } + xs = new String(in, start, stop - start, StandardCharsets.UTF_8); + } - protected int indexOf(char c, int pos) { - for (int i = pos; i < len; i++) - if (in[i] == (byte) c) - return i; - return -1; - } + protected int indexOf(char c, int pos) { + for (int i = pos; i < len; i++) if (in[i] == (byte) c) return i; + return -1; + } - protected void read() { - if (++pos >= len) - this.c = EOI; - else - this.c = (char) in[pos]; - } + protected void read() { + if (++pos >= len) this.c = EOI; + else this.c = (char) in[pos]; + } - /** - * Same as read() in memory parsing - */ - protected void readS() { - if (++pos >= len) - this.c = EOI; - else - this.c = (char) in[pos]; - } + /** Same as read() in memory parsing */ + protected void readS() { + if (++pos >= len) this.c = EOI; + else this.c = (char) in[pos]; + } - /** - * read data can not be EOI - */ - protected void readNoEnd() throws ParseException { - if (++pos >= len) { - this.c = EOI; - throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); - } else - this.c = (char) in[pos]; - } + /** read data can not be EOI */ + protected void readNoEnd() throws ParseException { + if (++pos >= len) { + this.c = EOI; + throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); + } else this.c = (char) in[pos]; + } } diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserInputStream.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserInputStream.java index b991274..076b302 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserInputStream.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserInputStream.java @@ -19,47 +19,48 @@ import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; - import net.minidev.json.writer.JsonReaderI; /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * + * * @author Uriel Chemouni <uchemouni@gmail.com> */ class JSONParserInputStream extends JSONParserReader { - // len - public JSONParserInputStream(int permissiveMode) { - super(permissiveMode); - } + // len + public JSONParserInputStream(int permissiveMode) { + super(permissiveMode); + } - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - * @throws UnsupportedEncodingException - */ - public Object parse(InputStream in) throws ParseException, UnsupportedEncodingException { - InputStreamReader i2 = new InputStreamReader(in, StandardCharsets.UTF_8); - return super.parse(i2); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + * + * @throws UnsupportedEncodingException + */ + public Object parse(InputStream in) throws ParseException, UnsupportedEncodingException { + InputStreamReader i2 = new InputStreamReader(in, StandardCharsets.UTF_8); + return super.parse(i2); + } - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(InputStream in, JsonReaderI mapper) throws ParseException, UnsupportedEncodingException { - InputStreamReader i2 = new InputStreamReader(in, StandardCharsets.UTF_8); - // - return super.parse(i2, mapper); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(InputStream in, JsonReaderI mapper) + throws ParseException, UnsupportedEncodingException { + InputStreamReader i2 = new InputStreamReader(in, StandardCharsets.UTF_8); + // + return super.parse(i2, mapper); + } - // - // - // - // - // - // - // - // + // + // + // + // + // + // + // + // } diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserMemory.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserMemory.java index b070ed2..edf9d8d 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserMemory.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserMemory.java @@ -23,118 +23,112 @@ /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * + * * @author Uriel Chemouni <uchemouni@gmail.com> * @see JSONParserString * @see JSONParserByteArray */ abstract class JSONParserMemory extends JSONParserBase { - protected int len; + protected int len; - public JSONParserMemory(int permissiveMode) { - super(permissiveMode); - } + public JSONParserMemory(int permissiveMode) { + super(permissiveMode); + } - protected void readNQString(boolean[] stop) throws IOException { - int start = pos; - skipNQString(stop); - extractStringTrim(start, pos); - } + protected void readNQString(boolean[] stop) throws IOException { + int start = pos; + skipNQString(stop); + extractStringTrim(start, pos); + } - protected Object readNumber(boolean[] stop) throws ParseException, IOException { - int start = pos; - // accept first char digit or - - read(); - skipDigits(); + protected Object readNumber(boolean[] stop) throws ParseException, IOException { + int start = pos; + // accept first char digit or - + read(); + skipDigits(); - // Integer digit - if (c != '.' && c != 'E' && c != 'e') { - skipSpace(); - if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { - // convert string - skipNQString(stop); - extractStringTrim(start, pos); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - return xs; - } - extractStringTrim(start, pos); - return parseNumber(xs); - } - // floating point - if (c == '.') { - // - read(); - skipDigits(); - } - if (c != 'E' && c != 'e') { - skipSpace(); - if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { - // convert string - skipNQString(stop); - extractStringTrim(start, pos); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - return xs; - } - extractStringTrim(start, pos); - return extractFloat(); - } - sb.append('E'); - read(); - if (c == '+' || c == '-' || c >= '0' && c <= '9') { - sb.append(c); - read(); // skip first char - skipDigits(); - skipSpace(); - if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { - // convert string - skipNQString(stop); - extractStringTrim(start, pos); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - return xs; - } - extractStringTrim(start, pos); - return extractFloat(); - } else { - skipNQString(stop); - extractStringTrim(start, pos); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - if (!acceptLeadinZero) - checkLeadinZero(); - return xs; - } - // throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, null); - } + // Integer digit + if (c != '.' && c != 'E' && c != 'e') { + skipSpace(); + if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { + // convert string + skipNQString(stop); + extractStringTrim(start, pos); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + return xs; + } + extractStringTrim(start, pos); + return parseNumber(xs); + } + // floating point + if (c == '.') { + // + read(); + skipDigits(); + } + if (c != 'E' && c != 'e') { + skipSpace(); + if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { + // convert string + skipNQString(stop); + extractStringTrim(start, pos); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + return xs; + } + extractStringTrim(start, pos); + return extractFloat(); + } + sb.append('E'); + read(); + if (c == '+' || c == '-' || c >= '0' && c <= '9') { + sb.append(c); + read(); // skip first char + skipDigits(); + skipSpace(); + if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { + // convert string + skipNQString(stop); + extractStringTrim(start, pos); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + return xs; + } + extractStringTrim(start, pos); + return extractFloat(); + } else { + skipNQString(stop); + extractStringTrim(start, pos); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + if (!acceptLeadinZero) checkLeadinZero(); + return xs; + } + // throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, null); + } - protected void readString() throws ParseException, IOException { - if (!acceptSimpleQuote && c == '\'') { - if (acceptNonQuote) { - readNQString(stopAll); - return; - } - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); - } - int tmpP = indexOf(c, pos + 1); - if (tmpP == -1) - throw new ParseException(len, ERROR_UNEXPECTED_EOF, null); - extractString(pos + 1, tmpP); - if (xs.indexOf('\\') == -1) { - checkControleChar(); - pos = tmpP; - read(); - // handler.primitive(tmp); - return; - } - sb.clear(); - readString2(); - } + protected void readString() throws ParseException, IOException { + if (!acceptSimpleQuote && c == '\'') { + if (acceptNonQuote) { + readNQString(stopAll); + return; + } + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); + } + int tmpP = indexOf(c, pos + 1); + if (tmpP == -1) throw new ParseException(len, ERROR_UNEXPECTED_EOF, null); + extractString(pos + 1, tmpP); + if (xs.indexOf('\\') == -1) { + checkControleChar(); + pos = tmpP; + read(); + // handler.primitive(tmp); + return; + } + sb.clear(); + readString2(); + } - abstract protected void extractString(int start, int stop); + protected abstract void extractString(int start, int stop); - abstract protected int indexOf(char c, int pos); + protected abstract int indexOf(char c, int pos); - abstract protected void extractStringTrim(int start, int stop); + protected abstract void extractStringTrim(int start, int stop); } diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserReader.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserReader.java index b33341c..2b0169b 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserReader.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserReader.java @@ -19,73 +19,71 @@ import java.io.IOException; import java.io.Reader; - import net.minidev.json.JSONValue; import net.minidev.json.writer.JsonReaderI; /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * + * * @author Uriel Chemouni <uchemouni@gmail.com> */ class JSONParserReader extends JSONParserStream { - private Reader in; + private Reader in; - // len - public JSONParserReader(int permissiveMode) { - super(permissiveMode); - } + // len + public JSONParserReader(int permissiveMode) { + super(permissiveMode); + } - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public Object parse(Reader in) throws ParseException { - return parse(in, JSONValue.defaultReader.DEFAULT); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public Object parse(Reader in) throws ParseException { + return parse(in, JSONValue.defaultReader.DEFAULT); + } - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(Reader in, JsonReaderI mapper) throws ParseException { - this.base = mapper.base; - // - this.in = in; - return super.parse(mapper); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(Reader in, JsonReaderI mapper) throws ParseException { + this.base = mapper.base; + // + this.in = in; + return super.parse(mapper); + } - // - // - // - // - // - // - // + // + // + // + // + // + // + // - protected void read() throws IOException { - int i = in.read(); - c = (i == -1) ? (char) EOI : (char) i; - pos++; - // - } + protected void read() throws IOException { + int i = in.read(); + c = (i == -1) ? (char) EOI : (char) i; + pos++; + // + } - protected void readS() throws IOException { - sb.append(c); - int i = in.read(); - if (i == -1) { - c = EOI; - } else { - c = (char) i; - pos++; - } - } + protected void readS() throws IOException { + sb.append(c); + int i = in.read(); + if (i == -1) { + c = EOI; + } else { + c = (char) i; + pos++; + } + } - protected void readNoEnd() throws ParseException, IOException { - int i = in.read(); - if (i == -1) - throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); - c = (char) i; - // - } + protected void readNoEnd() throws ParseException, IOException { + int i = in.read(); + if (i == -1) throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); + c = (char) i; + // + } } diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserStream.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserStream.java index 53f83c6..dbcc938 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserStream.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserStream.java @@ -22,121 +22,116 @@ /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * + * * @author Uriel Chemouni <uchemouni@gmail.com> * @see JSONParserInputStream * @see JSONParserReader */ abstract class JSONParserStream extends JSONParserBase { - // len - // - public JSONParserStream(int permissiveMode) { - super(permissiveMode); - } + // len + // + public JSONParserStream(int permissiveMode) { + super(permissiveMode); + } - protected void readNQString(boolean[] stop) throws IOException { - sb.clear(); - skipNQString(stop); - xs = sb.toString().trim(); - } + protected void readNQString(boolean[] stop) throws IOException { + sb.clear(); + skipNQString(stop); + xs = sb.toString().trim(); + } - protected Object readNumber(boolean[] stop) throws ParseException, IOException { - sb.clear(); - sb.append(c);// accept first char digit or - - read(); - skipDigits(); + protected Object readNumber(boolean[] stop) throws ParseException, IOException { + sb.clear(); + sb.append(c); // accept first char digit or - + read(); + skipDigits(); - // Integer digit - if (c != '.' && c != 'E' && c != 'e') { - skipSpace(); - if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { - // convert string - skipNQString(stop); - xs = sb.toString().trim(); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - return xs; - } - xs = sb.toString().trim(); - return parseNumber(xs); - } - // floating point - if (c == '.') { - sb.append(c); - read(); - skipDigits(); - } - if (c != 'E' && c != 'e') { - skipSpace(); - if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { - // convert string - skipNQString(stop); - xs = sb.toString().trim(); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - return xs; - } - xs = sb.toString().trim(); - return extractFloat(); - } - sb.append('E'); - read(); - if (c == '+' || c == '-' || c >= '0' && c <= '9') { - sb.append(c); - read(); // skip first char - skipDigits(); - skipSpace(); - if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { - // convert string - skipNQString(stop); - xs = sb.toString().trim(); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - return xs; - } - xs = sb.toString().trim(); - return extractFloat(); - } else { - skipNQString(stop); - xs = sb.toString().trim(); - if (!acceptNonQuote) - throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); - if (!acceptLeadinZero) - checkLeadinZero(); - return xs; - } - // throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, null); - } + // Integer digit + if (c != '.' && c != 'E' && c != 'e') { + skipSpace(); + if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { + // convert string + skipNQString(stop); + xs = sb.toString().trim(); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + return xs; + } + xs = sb.toString().trim(); + return parseNumber(xs); + } + // floating point + if (c == '.') { + sb.append(c); + read(); + skipDigits(); + } + if (c != 'E' && c != 'e') { + skipSpace(); + if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { + // convert string + skipNQString(stop); + xs = sb.toString().trim(); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + return xs; + } + xs = sb.toString().trim(); + return extractFloat(); + } + sb.append('E'); + read(); + if (c == '+' || c == '-' || c >= '0' && c <= '9') { + sb.append(c); + read(); // skip first char + skipDigits(); + skipSpace(); + if (c >= 0 && c < MAX_STOP && !stop[c] && c != EOI) { + // convert string + skipNQString(stop); + xs = sb.toString().trim(); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + return xs; + } + xs = sb.toString().trim(); + return extractFloat(); + } else { + skipNQString(stop); + xs = sb.toString().trim(); + if (!acceptNonQuote) throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs); + if (!acceptLeadinZero) checkLeadinZero(); + return xs; + } + // throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, null); + } - protected void readString() throws ParseException, IOException { - if (!acceptSimpleQuote && c == '\'') { - if (acceptNonQuote) { - readNQString(stopAll); - return; - } - throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); - } - sb.clear(); - // - // - // - // - // - // - // - // - // - // - /* assert (c == '\"' || c == '\'') */ - readString2(); - } + protected void readString() throws ParseException, IOException { + if (!acceptSimpleQuote && c == '\'') { + if (acceptNonQuote) { + readNQString(stopAll); + return; + } + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c); + } + sb.clear(); + // + // + // + // + // + // + // + // + // + // + /* assert (c == '\"' || c == '\'') */ + readString2(); + } - // - // - // - // - // - // - // - // + // + // + // + // + // + // + // + // } diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserString.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserString.java index 98420e4..4d505e2 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserString.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserString.java @@ -16,94 +16,84 @@ * limitations under the License. */ import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_EOF; + import net.minidev.json.JSONValue; import net.minidev.json.writer.JsonReaderI; /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. - * + * * @author Uriel Chemouni <uchemouni@gmail.com> */ class JSONParserString extends JSONParserMemory { - private String in; + private String in; - public JSONParserString(int permissiveMode) { - super(permissiveMode); - } + public JSONParserString(int permissiveMode) { + super(permissiveMode); + } - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public Object parse(String in) throws ParseException { - return parse(in, JSONValue.defaultReader.DEFAULT); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public Object parse(String in) throws ParseException { + return parse(in, JSONValue.defaultReader.DEFAULT); + } - // - // - // - // - // - // - // + // + // + // + // + // + // + // - /** - * use to return Primitive Type, or String, Or JsonObject or JsonArray - * generated by a ContainerFactory - */ - public T parse(String in, JsonReaderI mapper) throws ParseException { - this.base = mapper.base; - this.in = in; - this.len = in.length(); - return parse(mapper); - } + /** + * use to return Primitive Type, or String, Or JsonObject or JsonArray generated by a + * ContainerFactory + */ + public T parse(String in, JsonReaderI mapper) throws ParseException { + this.base = mapper.base; + this.in = in; + this.len = in.length(); + return parse(mapper); + } - protected void extractString(int beginIndex, int endIndex) { - xs = in.substring(beginIndex, endIndex); - } + protected void extractString(int beginIndex, int endIndex) { + xs = in.substring(beginIndex, endIndex); + } - protected void extractStringTrim(int start, int stop) { - while (start < stop-1 && Character.isWhitespace(in.charAt(start))) { - start++; - } - while (stop-1 > start && Character.isWhitespace(in.charAt(stop-1))) { - stop--; - } - extractString(start, stop); - } + protected void extractStringTrim(int start, int stop) { + while (start < stop - 1 && Character.isWhitespace(in.charAt(start))) { + start++; + } + while (stop - 1 > start && Character.isWhitespace(in.charAt(stop - 1))) { + stop--; + } + extractString(start, stop); + } - protected int indexOf(char c, int pos) { - return in.indexOf(c, pos); - } + protected int indexOf(char c, int pos) { + return in.indexOf(c, pos); + } - /** - * Read next char or END OF INPUT - */ - protected void read() { - if (++pos >= len) - this.c = EOI; - else - this.c = in.charAt(pos); - } + /** Read next char or END OF INPUT */ + protected void read() { + if (++pos >= len) this.c = EOI; + else this.c = in.charAt(pos); + } - /** - * Same as read() in memory parsing - */ - protected void readS() { - if (++pos >= len) - this.c = EOI; - else - this.c = in.charAt(pos); - } + /** Same as read() in memory parsing */ + protected void readS() { + if (++pos >= len) this.c = EOI; + else this.c = in.charAt(pos); + } - /** - * read data can not be EOI - */ - protected void readNoEnd() throws ParseException { - if (++pos >= len) { - this.c = EOI; - throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); - } else - this.c = in.charAt(pos); - } + /** read data can not be EOI */ + protected void readNoEnd() throws ParseException { + if (++pos >= len) { + this.c = EOI; + throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF"); + } else this.c = in.charAt(pos); + } } diff --git a/json-smart/src/main/java/net/minidev/json/parser/ParseException.java b/json-smart/src/main/java/net/minidev/json/parser/ParseException.java index 2b8d06d..b8cf012 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/ParseException.java +++ b/json-smart/src/main/java/net/minidev/json/parser/ParseException.java @@ -17,116 +17,113 @@ */ /** * ParseException explains why and where the error occurs in source JSON text. - * + * * @author Uriel Chemouni <uchemouni@gmail.com> */ public class ParseException extends Exception { - private static final long serialVersionUID = 8879024178584091857L; - - public static final int ERROR_UNEXPECTED_CHAR = 0; - public static final int ERROR_UNEXPECTED_TOKEN = 1; - public static final int ERROR_UNEXPECTED_EXCEPTION = 2; - public static final int ERROR_UNEXPECTED_EOF = 3; - public static final int ERROR_UNEXPECTED_UNICODE = 4; - public static final int ERROR_UNEXPECTED_DUPLICATE_KEY = 5; - public static final int ERROR_UNEXPECTED_LEADING_0 = 6; - public static final int ERROR_UNEXPECTED_JSON_DEPTH = 7; + private static final long serialVersionUID = 8879024178584091857L; - private int errorType; - private Object unexpectedObject; - private int position; + public static final int ERROR_UNEXPECTED_CHAR = 0; + public static final int ERROR_UNEXPECTED_TOKEN = 1; + public static final int ERROR_UNEXPECTED_EXCEPTION = 2; + public static final int ERROR_UNEXPECTED_EOF = 3; + public static final int ERROR_UNEXPECTED_UNICODE = 4; + public static final int ERROR_UNEXPECTED_DUPLICATE_KEY = 5; + public static final int ERROR_UNEXPECTED_LEADING_0 = 6; + public static final int ERROR_UNEXPECTED_JSON_DEPTH = 7; - public ParseException(int position, int errorType, Object unexpectedObject) { - super(toMessage(position, errorType, unexpectedObject)); - this.position = position; - this.errorType = errorType; - this.unexpectedObject = unexpectedObject; - } + private int errorType; + private Object unexpectedObject; + private int position; - public ParseException(int position, Throwable cause) { - super(toMessage(position, ERROR_UNEXPECTED_EXCEPTION, cause), cause); - this.position = position; - this.errorType = ERROR_UNEXPECTED_EXCEPTION; - this.unexpectedObject = cause; - } + public ParseException(int position, int errorType, Object unexpectedObject) { + super(toMessage(position, errorType, unexpectedObject)); + this.position = position; + this.errorType = errorType; + this.unexpectedObject = unexpectedObject; + } - public int getErrorType() { - return errorType; - } + public ParseException(int position, Throwable cause) { + super(toMessage(position, ERROR_UNEXPECTED_EXCEPTION, cause), cause); + this.position = position; + this.errorType = ERROR_UNEXPECTED_EXCEPTION; + this.unexpectedObject = cause; + } - /** - * @return The character position (starting with 0) of the input where the - * error occurs. - */ - public int getPosition() { - return position; - } + public int getErrorType() { + return errorType; + } - /** - * @return One of the following base on the value of errorType: - * ERROR_UNEXPECTED_CHAR java.lang.Character ERROR_UNEXPECTED_TOKEN - * ERROR_UNEXPECTED_EXCEPTION java.lang.Exception - */ - public Object getUnexpectedObject() { - return unexpectedObject; - } + /** + * @return The character position (starting with 0) of the input where the error occurs. + */ + public int getPosition() { + return position; + } - private static String toMessage(int position, int errorType, Object unexpectedObject) { - StringBuilder sb = new StringBuilder(); + /** + * @return One of the following base on the value of errorType: ERROR_UNEXPECTED_CHAR + * java.lang.Character ERROR_UNEXPECTED_TOKEN ERROR_UNEXPECTED_EXCEPTION java.lang.Exception + */ + public Object getUnexpectedObject() { + return unexpectedObject; + } - if (errorType == ERROR_UNEXPECTED_CHAR) { - sb.append("Unexpected character ("); - sb.append(unexpectedObject); - sb.append(") at position "); - sb.append(position); - sb.append("."); - } else if (errorType == ERROR_UNEXPECTED_TOKEN) { - sb.append("Unexpected token "); - sb.append(unexpectedObject); - sb.append(" at position "); - sb.append(position); - sb.append("."); - } else if (errorType == ERROR_UNEXPECTED_EXCEPTION) { - sb.append("Unexpected exception "); - sb.append(unexpectedObject); - sb.append(" occur at position "); - sb.append(position); - sb.append("."); - } else if (errorType == ERROR_UNEXPECTED_EOF) { - sb.append("Unexpected End Of File position "); - sb.append(position); - sb.append(": "); - sb.append(unexpectedObject); - } else if (errorType == ERROR_UNEXPECTED_UNICODE) { - sb.append("Unexpected unicode escape sequence "); - sb.append(unexpectedObject); - sb.append(" at position "); - sb.append(position); - sb.append("."); - } else if (errorType == ERROR_UNEXPECTED_DUPLICATE_KEY) { - sb.append("Unexpected duplicate key:"); - sb.append(unexpectedObject); - sb.append(" at position "); - sb.append(position); - sb.append("."); - } else if (errorType == ERROR_UNEXPECTED_LEADING_0) { - sb.append("Unexpected leading 0 in digit for token:"); - sb.append(unexpectedObject); - sb.append(" at position "); - sb.append(position); - sb.append("."); - } else if (errorType == ERROR_UNEXPECTED_JSON_DEPTH) { - sb.append("Malicious payload, having non natural depths, parsing stoped on "); - sb.append(unexpectedObject); - sb.append(" at position "); - sb.append(position); - sb.append("."); - } else { - sb.append("Unkown error at position "); - sb.append(position); - sb.append("."); - } - return sb.toString(); - } + private static String toMessage(int position, int errorType, Object unexpectedObject) { + StringBuilder sb = new StringBuilder(); + if (errorType == ERROR_UNEXPECTED_CHAR) { + sb.append("Unexpected character ("); + sb.append(unexpectedObject); + sb.append(") at position "); + sb.append(position); + sb.append("."); + } else if (errorType == ERROR_UNEXPECTED_TOKEN) { + sb.append("Unexpected token "); + sb.append(unexpectedObject); + sb.append(" at position "); + sb.append(position); + sb.append("."); + } else if (errorType == ERROR_UNEXPECTED_EXCEPTION) { + sb.append("Unexpected exception "); + sb.append(unexpectedObject); + sb.append(" occur at position "); + sb.append(position); + sb.append("."); + } else if (errorType == ERROR_UNEXPECTED_EOF) { + sb.append("Unexpected End Of File position "); + sb.append(position); + sb.append(": "); + sb.append(unexpectedObject); + } else if (errorType == ERROR_UNEXPECTED_UNICODE) { + sb.append("Unexpected unicode escape sequence "); + sb.append(unexpectedObject); + sb.append(" at position "); + sb.append(position); + sb.append("."); + } else if (errorType == ERROR_UNEXPECTED_DUPLICATE_KEY) { + sb.append("Unexpected duplicate key:"); + sb.append(unexpectedObject); + sb.append(" at position "); + sb.append(position); + sb.append("."); + } else if (errorType == ERROR_UNEXPECTED_LEADING_0) { + sb.append("Unexpected leading 0 in digit for token:"); + sb.append(unexpectedObject); + sb.append(" at position "); + sb.append(position); + sb.append("."); + } else if (errorType == ERROR_UNEXPECTED_JSON_DEPTH) { + sb.append("Malicious payload, having non natural depths, parsing stoped on "); + sb.append(unexpectedObject); + sb.append(" at position "); + sb.append(position); + sb.append("."); + } else { + sb.append("Unkown error at position "); + sb.append(position); + sb.append("."); + } + return sb.toString(); + } } diff --git a/json-smart/src/main/java/net/minidev/json/reader/ArrayWriter.java b/json-smart/src/main/java/net/minidev/json/reader/ArrayWriter.java index 4341a26..04716c0 100644 --- a/json-smart/src/main/java/net/minidev/json/reader/ArrayWriter.java +++ b/json-smart/src/main/java/net/minidev/json/reader/ArrayWriter.java @@ -1,21 +1,19 @@ package net.minidev.json.reader; import java.io.IOException; - import net.minidev.json.JSONStyle; import net.minidev.json.JSONValue; public class ArrayWriter implements JsonWriterI { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - compression.arrayStart(out); - boolean needSep = false; - for (Object o : ((Object[]) value)) { - if (needSep) - compression.objectNext(out); - else - needSep = true; - JSONValue.writeJSONString(o, out, compression); - } - compression.arrayStop(out); - } + public void writeJSONString(E value, Appendable out, JSONStyle compression) + throws IOException { + compression.arrayStart(out); + boolean needSep = false; + for (Object o : ((Object[]) value)) { + if (needSep) compression.objectNext(out); + else needSep = true; + JSONValue.writeJSONString(o, out, compression); + } + compression.arrayStop(out); + } } diff --git a/json-smart/src/main/java/net/minidev/json/reader/BeansWriter.java b/json-smart/src/main/java/net/minidev/json/reader/BeansWriter.java index 5644db3..9623ffc 100644 --- a/json-smart/src/main/java/net/minidev/json/reader/BeansWriter.java +++ b/json-smart/src/main/java/net/minidev/json/reader/BeansWriter.java @@ -4,60 +4,55 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; - import net.minidev.json.JSONStyle; import net.minidev.json.JSONUtil; public class BeansWriter implements JsonWriterI { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - try { - Class nextClass = value.getClass(); - boolean needSep = false; - compression.objectStart(out); - while (nextClass != Object.class) { - Field[] fields = nextClass.getDeclaredFields(); - for (Field field : fields) { - int m = field.getModifiers(); - if ((m & (Modifier.STATIC | Modifier.TRANSIENT | Modifier.FINAL)) > 0) - continue; - Object v = null; - if ((m & Modifier.PUBLIC) > 0) { - v = field.get(value); - } else { - String g = JSONUtil.getGetterName(field.getName()); - Method mtd = null; + public void writeJSONString(E value, Appendable out, JSONStyle compression) + throws IOException { + try { + Class nextClass = value.getClass(); + boolean needSep = false; + compression.objectStart(out); + while (nextClass != Object.class) { + Field[] fields = nextClass.getDeclaredFields(); + for (Field field : fields) { + int m = field.getModifiers(); + if ((m & (Modifier.STATIC | Modifier.TRANSIENT | Modifier.FINAL)) > 0) continue; + Object v = null; + if ((m & Modifier.PUBLIC) > 0) { + v = field.get(value); + } else { + String g = JSONUtil.getGetterName(field.getName()); + Method mtd = null; - try { - mtd = nextClass.getDeclaredMethod(g); - } catch (Exception e) { - } - if (mtd == null) { - Class c2 = field.getType(); - if (c2 == Boolean.TYPE || c2 == Boolean.class) { - g = JSONUtil.getIsName(field.getName()); - mtd = nextClass.getDeclaredMethod(g); - } - } - if (mtd == null) - continue; - v = mtd.invoke(value); - } - if (v == null && compression.ignoreNull()) - continue; - if (needSep) - compression.objectNext(out); - else - needSep = true; - String key = field.getName(); + try { + mtd = nextClass.getDeclaredMethod(g); + } catch (Exception e) { + } + if (mtd == null) { + Class c2 = field.getType(); + if (c2 == Boolean.TYPE || c2 == Boolean.class) { + g = JSONUtil.getIsName(field.getName()); + mtd = nextClass.getDeclaredMethod(g); + } + } + if (mtd == null) continue; + v = mtd.invoke(value); + } + if (v == null && compression.ignoreNull()) continue; + if (needSep) compression.objectNext(out); + else needSep = true; + String key = field.getName(); - JsonWriter.writeJSONKV(key, v, out, compression); - // compression.objectElmStop(out); - } - nextClass = nextClass.getSuperclass(); - } - compression.objectStop(out); - } catch (Exception e) { - throw new RuntimeException(e); - } - } + JsonWriter.writeJSONKV(key, v, out, compression); + // compression.objectElmStop(out); + } + nextClass = nextClass.getSuperclass(); + } + compression.objectStop(out); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASM.java b/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASM.java index 7b1feb0..2c50aa3 100644 --- a/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASM.java +++ b/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASM.java @@ -1,7 +1,6 @@ package net.minidev.json.reader; import java.io.IOException; - import net.minidev.asm.Accessor; import net.minidev.asm.BeansAccess; import net.minidev.json.JSONObject; @@ -9,28 +8,26 @@ import net.minidev.json.JSONUtil; public class BeansWriterASM implements JsonWriterI { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - try { - Class cls = value.getClass(); - boolean needSep = false; - @SuppressWarnings("rawtypes") - BeansAccess fields = BeansAccess.get(cls, JSONUtil.JSON_SMART_FIELD_FILTER); - out.append('{'); - for (Accessor field : fields.getAccessors()) { - @SuppressWarnings("unchecked") - Object v = fields.get(value, field.getIndex()); - if (v == null && compression.ignoreNull()) - continue; - if (needSep) - out.append(','); - else - needSep = true; - String key = field.getName(); - JSONObject.writeJSONKV(key, v, out, compression); - } - out.append('}'); - } catch (IOException e) { - throw e; - } - } + public void writeJSONString(E value, Appendable out, JSONStyle compression) + throws IOException { + try { + Class cls = value.getClass(); + boolean needSep = false; + @SuppressWarnings("rawtypes") + BeansAccess fields = BeansAccess.get(cls, JSONUtil.JSON_SMART_FIELD_FILTER); + out.append('{'); + for (Accessor field : fields.getAccessors()) { + @SuppressWarnings("unchecked") + Object v = fields.get(value, field.getIndex()); + if (v == null && compression.ignoreNull()) continue; + if (needSep) out.append(','); + else needSep = true; + String key = field.getName(); + JSONObject.writeJSONKV(key, v, out, compression); + } + out.append('}'); + } catch (IOException e) { + throw e; + } + } } diff --git a/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASMRemap.java b/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASMRemap.java index c9b9137..10c41ed 100644 --- a/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASMRemap.java +++ b/json-smart/src/main/java/net/minidev/json/reader/BeansWriterASMRemap.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; - import net.minidev.asm.Accessor; import net.minidev.asm.BeansAccess; import net.minidev.json.JSONObject; @@ -11,43 +10,39 @@ import net.minidev.json.JSONUtil; public class BeansWriterASMRemap implements JsonWriterI { - private Map rename = new HashMap(); - - public void renameField(String source, String dest) { - rename.put(source, dest); - } + private Map rename = new HashMap(); - private String rename(String key) { - String k2 = rename.get(key); - if (k2 != null) - return k2; - return key; - } + public void renameField(String source, String dest) { + rename.put(source, dest); + } - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - try { - Class cls = value.getClass(); - boolean needSep = false; - @SuppressWarnings("rawtypes") - BeansAccess fields = BeansAccess.get(cls, JSONUtil.JSON_SMART_FIELD_FILTER); - out.append('{'); - for (Accessor field : fields.getAccessors()) { - @SuppressWarnings("unchecked") - Object v = fields.get(value, field.getIndex()); - if (v == null && compression.ignoreNull()) - continue; - if (needSep) - out.append(','); - else - needSep = true; - String key = field.getName(); - key = rename(key); - JSONObject.writeJSONKV(key, v, out, compression); - } - out.append('}'); - } catch (IOException e) { - throw e; - } - } + private String rename(String key) { + String k2 = rename.get(key); + if (k2 != null) return k2; + return key; + } + public void writeJSONString(E value, Appendable out, JSONStyle compression) + throws IOException { + try { + Class cls = value.getClass(); + boolean needSep = false; + @SuppressWarnings("rawtypes") + BeansAccess fields = BeansAccess.get(cls, JSONUtil.JSON_SMART_FIELD_FILTER); + out.append('{'); + for (Accessor field : fields.getAccessors()) { + @SuppressWarnings("unchecked") + Object v = fields.get(value, field.getIndex()); + if (v == null && compression.ignoreNull()) continue; + if (needSep) out.append(','); + else needSep = true; + String key = field.getName(); + key = rename(key); + JSONObject.writeJSONKV(key, v, out, compression); + } + out.append('}'); + } catch (IOException e) { + throw e; + } + } } diff --git a/json-smart/src/main/java/net/minidev/json/reader/JsonWriter.java b/json-smart/src/main/java/net/minidev/json/reader/JsonWriter.java index 3d4a3a8..3b1c5fa 100644 --- a/json-smart/src/main/java/net/minidev/json/reader/JsonWriter.java +++ b/json-smart/src/main/java/net/minidev/json/reader/JsonWriter.java @@ -15,381 +15,403 @@ import net.minidev.json.JSONValue; public class JsonWriter { - private ConcurrentHashMap, JsonWriterI> data; - private LinkedList writerInterfaces; - - public JsonWriter() { - data = new ConcurrentHashMap, JsonWriterI>(); - writerInterfaces = new LinkedList(); - init(); - } - - /** - * remap field name in custom classes - * - * @param fromJava - * field name in java - * @param toJson - * field name in json - * @since 2.1.1 - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - public void remapField(Class type, String fromJava, String toJson) { - JsonWriterI map = this.getWrite(type); - if (!(map instanceof BeansWriterASMRemap)) { - map = new BeansWriterASMRemap(); - registerWriter(map, type); - } - ((BeansWriterASMRemap) map).renameField(fromJava, toJson); - } - - static class WriterByInterface { - public Class _interface; - public JsonWriterI _writer; - - public WriterByInterface(Class _interface, JsonWriterI _writer) { - this._interface = _interface; - this._writer = _writer; - } - } - - /** - * try to find a Writer by Checking implemented interface - * @param clazz class to serialize - * @return a Writer or null - */ - @SuppressWarnings("rawtypes") - public JsonWriterI getWriterByInterface(Class clazz) { - for (WriterByInterface w : writerInterfaces) { - if (w._interface.isAssignableFrom(clazz)) - return w._writer; - } - return null; - } - - @SuppressWarnings("rawtypes") - public JsonWriterI getWrite(Class cls) { - return data.get(cls); - } - - final static public JsonWriterI JSONStreamAwareWriter = new JsonWriterI() { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - value.writeJSONString(out); - } - }; - - final static public JsonWriterI JSONStreamAwareExWriter = new JsonWriterI() { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - value.writeJSONString(out, compression); - } - }; - - final static public JsonWriterI JSONJSONAwareExWriter = new JsonWriterI() { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - out.append(value.toJSONString(compression)); - } - }; - - final static public JsonWriterI JSONJSONAwareWriter = new JsonWriterI() { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - out.append(value.toJSONString()); - } - }; - - final static public JsonWriterI> JSONIterableWriter = new JsonWriterI>() { - public > void writeJSONString(E list, Appendable out, JSONStyle compression) throws IOException { - boolean first = true; - compression.arrayStart(out); - for (Object value : list) { - if (first) { - first = false; - compression.arrayfirstObject(out); - } else { - compression.arrayNextElm(out); - } - if (value == null) - out.append("null"); - else - JSONValue.writeJSONString(value, out, compression); - compression.arrayObjectEnd(out); - } - compression.arrayStop(out); - } - }; - - final static public JsonWriterI> EnumWriter = new JsonWriterI>() { - public > void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException { - @SuppressWarnings("rawtypes") - String s = ((Enum) value).name(); - compression.writeString(out, s); - } - }; - - final static public JsonWriterI> JSONMapWriter = new JsonWriterI>() { - public > void writeJSONString(E map, Appendable out, JSONStyle compression) throws IOException { - boolean first = true; - compression.objectStart(out); - /** - * do not use to handle non String key maps - */ - for (Map.Entry entry : map.entrySet()) { - Object v = entry.getValue(); - if (v == null && compression.ignoreNull()) - continue; - if (first) { - compression.objectFirstStart(out); - first = false; - } else { - compression.objectNext(out); - } - JsonWriter.writeJSONKV(entry.getKey().toString(), v, out, compression); - // compression.objectElmStop(out); - } - compression.objectStop(out); - } - }; - - /** - * Json-Smart V2 Beans serialiser - * - * Based on ASM - */ - final static public JsonWriterI beansWriterASM = new BeansWriterASM(); - - /** - * Json-Smart V1 Beans serialiser - */ - final static public JsonWriterI beansWriter = new BeansWriter(); - - /** - * Json-Smart ArrayWriterClass - */ - final static public JsonWriterI arrayWriter = new ArrayWriter(); - - /** - * ToString Writer - */ - final static public JsonWriterI toStringWriter = new JsonWriterI() { - public void writeJSONString(Object value, Appendable out, JSONStyle compression) throws IOException { - out.append(value.toString()); - } - }; - - public void init() { - registerWriter(new JsonWriterI() { - public void writeJSONString(String value, Appendable out, JSONStyle compression) throws IOException { - compression.writeString(out, (String) value); - } - }, String.class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(Double value, Appendable out, JSONStyle compression) throws IOException { - if (value.isInfinite()) - out.append("null"); - else - out.append(value.toString()); - } - }, Double.class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(Date value, Appendable out, JSONStyle compression) throws IOException { - out.append('"'); - JSONValue.escape(value.toString(), out, compression); - out.append('"'); - } - }, Date.class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(Float value, Appendable out, JSONStyle compression) throws IOException { - if (value.isInfinite()) - out.append("null"); - else - out.append(value.toString()); - } - }, Float.class); - - registerWriter(toStringWriter, Integer.class, Long.class, Byte.class, Short.class, BigInteger.class, BigDecimal.class); - registerWriter(toStringWriter, Boolean.class); - - /** - * Array - */ - - registerWriter(new JsonWriterI() { - public void writeJSONString(int[] value, Appendable out, JSONStyle compression) throws IOException { - boolean needSep = false; - compression.arrayStart(out); - for (int b : value) { - if (needSep) - compression.objectNext(out); - else - needSep = true; - out.append(Integer.toString(b)); - } - compression.arrayStop(out); - } - }, int[].class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(short[] value, Appendable out, JSONStyle compression) throws IOException { - boolean needSep = false; - compression.arrayStart(out); - for (short b : value) { - if (needSep) - compression.objectNext(out); - else - needSep = true; - out.append(Short.toString(b)); - } - compression.arrayStop(out); - } - }, short[].class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(long[] value, Appendable out, JSONStyle compression) throws IOException { - boolean needSep = false; - compression.arrayStart(out); - for (long b : value) { - if (needSep) - compression.objectNext(out); - else - needSep = true; - out.append(Long.toString(b)); - } - compression.arrayStop(out); - } - }, long[].class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(float[] value, Appendable out, JSONStyle compression) throws IOException { - boolean needSep = false; - compression.arrayStart(out); - for (float b : value) { - if (needSep) - compression.objectNext(out); - else - needSep = true; - out.append(Float.toString(b)); - } - compression.arrayStop(out); - } - }, float[].class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(double[] value, Appendable out, JSONStyle compression) throws IOException { - boolean needSep = false; - compression.arrayStart(out); - for (double b : value) { - if (needSep) - compression.objectNext(out); - else - needSep = true; - out.append(Double.toString(b)); - } - compression.arrayStop(out); - } - }, double[].class); - - registerWriter(new JsonWriterI() { - public void writeJSONString(boolean[] value, Appendable out, JSONStyle compression) throws IOException { - boolean needSep = false; - compression.arrayStart(out); - for (boolean b : value) { - if (needSep) - compression.objectNext(out); - else - needSep = true; - out.append(Boolean.toString(b)); - } - compression.arrayStop(out); - } - }, boolean[].class); - - registerWriterInterface(JSONStreamAwareEx.class, JsonWriter.JSONStreamAwareExWriter); - registerWriterInterface(JSONStreamAware.class, JsonWriter.JSONStreamAwareWriter); - registerWriterInterface(JSONAwareEx.class, JsonWriter.JSONJSONAwareExWriter); - registerWriterInterface(JSONAware.class, JsonWriter.JSONJSONAwareWriter); - registerWriterInterface(Map.class, JsonWriter.JSONMapWriter); - registerWriterInterface(Iterable.class, JsonWriter.JSONIterableWriter); - registerWriterInterface(Enum.class, JsonWriter.EnumWriter); - registerWriterInterface(Number.class, JsonWriter.toStringWriter); - } - - /** - * associate an Writer to a interface With Hi priority - * @param interFace interface to map - * @param writer writer Object - * @deprecated use registerWriterInterfaceFirst - */ - public void addInterfaceWriterFirst(Class interFace, JsonWriterI writer) { - registerWriterInterfaceFirst(interFace, writer); - } - - /** - * associate an Writer to a interface With Low priority - * @param interFace interface to map - * @param writer writer Object - * @deprecated use registerWriterInterfaceLast - */ - public void addInterfaceWriterLast(Class interFace, JsonWriterI writer) { - registerWriterInterfaceLast(interFace, writer); - } - - /** - * associate an Writer to a interface With Low priority - * @param interFace interface to map - * @param writer writer Object - */ - public void registerWriterInterfaceLast(Class interFace, JsonWriterI writer) { - writerInterfaces.addLast(new WriterByInterface(interFace, writer)); - } - - /** - * associate an Writer to a interface With Hi priority - * @param interFace interface to map - * @param writer writer Object - */ - public void registerWriterInterfaceFirst(Class interFace, JsonWriterI writer) { - writerInterfaces.addFirst(new WriterByInterface(interFace, writer)); - } - - /** - * an alias for registerWriterInterfaceLast - * @param interFace interface to map - * @param writer writer Object - */ - public void registerWriterInterface(Class interFace, JsonWriterI writer) { - registerWriterInterfaceLast(interFace, writer); - } - - /** - * associate an Writer to a Class - * @param writer - * @param cls - */ - public void registerWriter(JsonWriterI writer, Class... cls) { - for (Class c : cls) - data.put(c, writer); - } - - /** - * Write a Key : value entry to a stream - */ - public static void writeJSONKV(String key, Object value, Appendable out, JSONStyle compression) throws IOException { - if (key == null) - out.append("null"); - else if (!compression.mustProtectKey(key)) - out.append(key); - else { - out.append('"'); - JSONValue.escape(key, out, compression); - out.append('"'); - } - compression.objectEndOfKey(out); - if (value instanceof String) { - compression.writeString(out, (String) value); - } else - JSONValue.writeJSONString(value, out, compression); - compression.objectElmStop(out); - } + private ConcurrentHashMap, JsonWriterI> data; + private LinkedList writerInterfaces; + + public JsonWriter() { + data = new ConcurrentHashMap, JsonWriterI>(); + writerInterfaces = new LinkedList(); + init(); + } + + /** + * remap field name in custom classes + * + * @param fromJava field name in java + * @param toJson field name in json + * @since 2.1.1 + */ + @SuppressWarnings({"rawtypes", "unchecked"}) + public void remapField(Class type, String fromJava, String toJson) { + JsonWriterI map = this.getWrite(type); + if (!(map instanceof BeansWriterASMRemap)) { + map = new BeansWriterASMRemap(); + registerWriter(map, type); + } + ((BeansWriterASMRemap) map).renameField(fromJava, toJson); + } + + static class WriterByInterface { + public Class _interface; + public JsonWriterI _writer; + + public WriterByInterface(Class _interface, JsonWriterI _writer) { + this._interface = _interface; + this._writer = _writer; + } + } + + /** + * try to find a Writer by Checking implemented interface + * + * @param clazz class to serialize + * @return a Writer or null + */ + @SuppressWarnings("rawtypes") + public JsonWriterI getWriterByInterface(Class clazz) { + for (WriterByInterface w : writerInterfaces) { + if (w._interface.isAssignableFrom(clazz)) return w._writer; + } + return null; + } + + @SuppressWarnings("rawtypes") + public JsonWriterI getWrite(Class cls) { + return data.get(cls); + } + + public static final JsonWriterI JSONStreamAwareWriter = + new JsonWriterI() { + public void writeJSONString( + E value, Appendable out, JSONStyle compression) throws IOException { + value.writeJSONString(out); + } + }; + + public static final JsonWriterI JSONStreamAwareExWriter = + new JsonWriterI() { + public void writeJSONString( + E value, Appendable out, JSONStyle compression) throws IOException { + value.writeJSONString(out, compression); + } + }; + + public static final JsonWriterI JSONJSONAwareExWriter = + new JsonWriterI() { + public void writeJSONString( + E value, Appendable out, JSONStyle compression) throws IOException { + out.append(value.toJSONString(compression)); + } + }; + + public static final JsonWriterI JSONJSONAwareWriter = + new JsonWriterI() { + public void writeJSONString( + E value, Appendable out, JSONStyle compression) throws IOException { + out.append(value.toJSONString()); + } + }; + + public static final JsonWriterI> JSONIterableWriter = + new JsonWriterI>() { + public > void writeJSONString( + E list, Appendable out, JSONStyle compression) throws IOException { + boolean first = true; + compression.arrayStart(out); + for (Object value : list) { + if (first) { + first = false; + compression.arrayfirstObject(out); + } else { + compression.arrayNextElm(out); + } + if (value == null) out.append("null"); + else JSONValue.writeJSONString(value, out, compression); + compression.arrayObjectEnd(out); + } + compression.arrayStop(out); + } + }; + + public static final JsonWriterI> EnumWriter = + new JsonWriterI>() { + public > void writeJSONString( + E value, Appendable out, JSONStyle compression) throws IOException { + @SuppressWarnings("rawtypes") + String s = ((Enum) value).name(); + compression.writeString(out, s); + } + }; + + public static final JsonWriterI> JSONMapWriter = + new JsonWriterI>() { + public > void writeJSONString( + E map, Appendable out, JSONStyle compression) throws IOException { + boolean first = true; + compression.objectStart(out); + /** do not use to handle non String key maps */ + for (Map.Entry entry : map.entrySet()) { + Object v = entry.getValue(); + if (v == null && compression.ignoreNull()) continue; + if (first) { + compression.objectFirstStart(out); + first = false; + } else { + compression.objectNext(out); + } + JsonWriter.writeJSONKV(entry.getKey().toString(), v, out, compression); + // compression.objectElmStop(out); + } + compression.objectStop(out); + } + }; + + /** + * Json-Smart V2 Beans serialiser + * + *

Based on ASM + */ + public static final JsonWriterI beansWriterASM = new BeansWriterASM(); + + /** Json-Smart V1 Beans serialiser */ + public static final JsonWriterI beansWriter = new BeansWriter(); + + /** Json-Smart ArrayWriterClass */ + public static final JsonWriterI arrayWriter = new ArrayWriter(); + + /** ToString Writer */ + public static final JsonWriterI toStringWriter = + new JsonWriterI() { + public void writeJSONString(Object value, Appendable out, JSONStyle compression) + throws IOException { + out.append(value.toString()); + } + }; + + public void init() { + registerWriter( + new JsonWriterI() { + public void writeJSONString(String value, Appendable out, JSONStyle compression) + throws IOException { + compression.writeString(out, (String) value); + } + }, + String.class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(Double value, Appendable out, JSONStyle compression) + throws IOException { + if (value.isInfinite()) out.append("null"); + else out.append(value.toString()); + } + }, + Double.class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(Date value, Appendable out, JSONStyle compression) + throws IOException { + out.append('"'); + JSONValue.escape(value.toString(), out, compression); + out.append('"'); + } + }, + Date.class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(Float value, Appendable out, JSONStyle compression) + throws IOException { + if (value.isInfinite()) out.append("null"); + else out.append(value.toString()); + } + }, + Float.class); + + registerWriter( + toStringWriter, + Integer.class, + Long.class, + Byte.class, + Short.class, + BigInteger.class, + BigDecimal.class); + registerWriter(toStringWriter, Boolean.class); + + /** Array */ + registerWriter( + new JsonWriterI() { + public void writeJSONString(int[] value, Appendable out, JSONStyle compression) + throws IOException { + boolean needSep = false; + compression.arrayStart(out); + for (int b : value) { + if (needSep) compression.objectNext(out); + else needSep = true; + out.append(Integer.toString(b)); + } + compression.arrayStop(out); + } + }, + int[].class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(short[] value, Appendable out, JSONStyle compression) + throws IOException { + boolean needSep = false; + compression.arrayStart(out); + for (short b : value) { + if (needSep) compression.objectNext(out); + else needSep = true; + out.append(Short.toString(b)); + } + compression.arrayStop(out); + } + }, + short[].class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(long[] value, Appendable out, JSONStyle compression) + throws IOException { + boolean needSep = false; + compression.arrayStart(out); + for (long b : value) { + if (needSep) compression.objectNext(out); + else needSep = true; + out.append(Long.toString(b)); + } + compression.arrayStop(out); + } + }, + long[].class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(float[] value, Appendable out, JSONStyle compression) + throws IOException { + boolean needSep = false; + compression.arrayStart(out); + for (float b : value) { + if (needSep) compression.objectNext(out); + else needSep = true; + out.append(Float.toString(b)); + } + compression.arrayStop(out); + } + }, + float[].class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(double[] value, Appendable out, JSONStyle compression) + throws IOException { + boolean needSep = false; + compression.arrayStart(out); + for (double b : value) { + if (needSep) compression.objectNext(out); + else needSep = true; + out.append(Double.toString(b)); + } + compression.arrayStop(out); + } + }, + double[].class); + + registerWriter( + new JsonWriterI() { + public void writeJSONString(boolean[] value, Appendable out, JSONStyle compression) + throws IOException { + boolean needSep = false; + compression.arrayStart(out); + for (boolean b : value) { + if (needSep) compression.objectNext(out); + else needSep = true; + out.append(Boolean.toString(b)); + } + compression.arrayStop(out); + } + }, + boolean[].class); + + registerWriterInterface(JSONStreamAwareEx.class, JsonWriter.JSONStreamAwareExWriter); + registerWriterInterface(JSONStreamAware.class, JsonWriter.JSONStreamAwareWriter); + registerWriterInterface(JSONAwareEx.class, JsonWriter.JSONJSONAwareExWriter); + registerWriterInterface(JSONAware.class, JsonWriter.JSONJSONAwareWriter); + registerWriterInterface(Map.class, JsonWriter.JSONMapWriter); + registerWriterInterface(Iterable.class, JsonWriter.JSONIterableWriter); + registerWriterInterface(Enum.class, JsonWriter.EnumWriter); + registerWriterInterface(Number.class, JsonWriter.toStringWriter); + } + + /** + * associate an Writer to a interface With Hi priority + * + * @param interFace interface to map + * @param writer writer Object + * @deprecated use registerWriterInterfaceFirst + */ + public void addInterfaceWriterFirst(Class interFace, JsonWriterI writer) { + registerWriterInterfaceFirst(interFace, writer); + } + + /** + * associate an Writer to a interface With Low priority + * + * @param interFace interface to map + * @param writer writer Object + * @deprecated use registerWriterInterfaceLast + */ + public void addInterfaceWriterLast(Class interFace, JsonWriterI writer) { + registerWriterInterfaceLast(interFace, writer); + } + + /** + * associate an Writer to a interface With Low priority + * + * @param interFace interface to map + * @param writer writer Object + */ + public void registerWriterInterfaceLast(Class interFace, JsonWriterI writer) { + writerInterfaces.addLast(new WriterByInterface(interFace, writer)); + } + + /** + * associate an Writer to a interface With Hi priority + * + * @param interFace interface to map + * @param writer writer Object + */ + public void registerWriterInterfaceFirst(Class interFace, JsonWriterI writer) { + writerInterfaces.addFirst(new WriterByInterface(interFace, writer)); + } + + /** + * an alias for registerWriterInterfaceLast + * + * @param interFace interface to map + * @param writer writer Object + */ + public void registerWriterInterface(Class interFace, JsonWriterI writer) { + registerWriterInterfaceLast(interFace, writer); + } + + /** + * associate an Writer to a Class + * + * @param writer + * @param cls + */ + public void registerWriter(JsonWriterI writer, Class... cls) { + for (Class c : cls) data.put(c, writer); + } + + /** Write a Key : value entry to a stream */ + public static void writeJSONKV(String key, Object value, Appendable out, JSONStyle compression) + throws IOException { + if (key == null) out.append("null"); + else if (!compression.mustProtectKey(key)) out.append(key); + else { + out.append('"'); + JSONValue.escape(key, out, compression); + out.append('"'); + } + compression.objectEndOfKey(out); + if (value instanceof String) { + compression.writeString(out, (String) value); + } else JSONValue.writeJSONString(value, out, compression); + compression.objectElmStop(out); + } } diff --git a/json-smart/src/main/java/net/minidev/json/reader/JsonWriterI.java b/json-smart/src/main/java/net/minidev/json/reader/JsonWriterI.java index ee818bf..1da81fe 100644 --- a/json-smart/src/main/java/net/minidev/json/reader/JsonWriterI.java +++ b/json-smart/src/main/java/net/minidev/json/reader/JsonWriterI.java @@ -1,9 +1,9 @@ package net.minidev.json.reader; import java.io.IOException; - import net.minidev.json.JSONStyle; public interface JsonWriterI { - public void writeJSONString(E value, Appendable out, JSONStyle compression) throws IOException; + public void writeJSONString(E value, Appendable out, JSONStyle compression) + throws IOException; } diff --git a/json-smart/src/main/java/net/minidev/json/writer/ArraysMapper.java b/json-smart/src/main/java/net/minidev/json/writer/ArraysMapper.java index 66312ca..04db8e9 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/ArraysMapper.java +++ b/json-smart/src/main/java/net/minidev/json/writer/ArraysMapper.java @@ -20,290 +20,273 @@ import java.util.List; public class ArraysMapper extends JsonReaderI { - public ArraysMapper(JsonReader base) { - super(base); - } + public ArraysMapper(JsonReader base) { + super(base); + } - @Override - public Object createArray() { - return new ArrayList(); - } + @Override + public Object createArray() { + return new ArrayList(); + } - @SuppressWarnings("unchecked") - @Override - public void addValue(Object current, Object value) { - ((List) current).add(value); - } + @SuppressWarnings("unchecked") + @Override + public void addValue(Object current, Object value) { + ((List) current).add(value); + } - @SuppressWarnings("unchecked") - @Override - public T convert(Object current) { - return (T) current; - } + @SuppressWarnings("unchecked") + @Override + public T convert(Object current) { + return (T) current; + } - public static class GenericMapper extends ArraysMapper { - final Class componentType; - JsonReaderI subMapper; + public static class GenericMapper extends ArraysMapper { + final Class componentType; + JsonReaderI subMapper; - public GenericMapper(JsonReader base, Class type) { - super(base); - this.componentType = type.getComponentType(); - } + public GenericMapper(JsonReader base, Class type) { + super(base); + this.componentType = type.getComponentType(); + } - @SuppressWarnings("unchecked") - @Override - public T convert(Object current) { - int p = 0; + @SuppressWarnings("unchecked") + @Override + public T convert(Object current) { + int p = 0; - Object[] r = (Object[]) Array.newInstance(componentType, ((List) current).size()); - for (Object e : ((List) current)) - r[p++] = e; - return (T) r; - } + Object[] r = (Object[]) Array.newInstance(componentType, ((List) current).size()); + for (Object e : ((List) current)) r[p++] = e; + return (T) r; + } - @Override - public JsonReaderI startArray(String key) { - if (subMapper == null) - subMapper = base.getMapper(componentType); - return subMapper; - } + @Override + public JsonReaderI startArray(String key) { + if (subMapper == null) subMapper = base.getMapper(componentType); + return subMapper; + } - @Override - public JsonReaderI startObject(String key) { - if (subMapper == null) - subMapper = base.getMapper(componentType); - return subMapper; - } - }; + @Override + public JsonReaderI startObject(String key) { + if (subMapper == null) subMapper = base.getMapper(componentType); + return subMapper; + } + } + ; - public static JsonReaderI MAPPER_PRIM_INT = new ArraysMapper(null) { - @Override - public int[] convert(Object current) { - int p = 0; - int[] r = new int[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = ((Number) e).intValue(); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_INT = + new ArraysMapper(null) { + @Override + public int[] convert(Object current) { + int p = 0; + int[] r = new int[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = ((Number) e).intValue(); + return r; + } + }; - public static JsonReaderI MAPPER_INT = new ArraysMapper(null) { - @Override - public Integer[] convert(Object current) { - int p = 0; - Integer[] r = new Integer[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - if (e instanceof Integer) - r[p] = (Integer) e; - else - r[p] = ((Number) e).intValue(); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_INT = + new ArraysMapper(null) { + @Override + public Integer[] convert(Object current) { + int p = 0; + Integer[] r = new Integer[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + if (e instanceof Integer) r[p] = (Integer) e; + else r[p] = ((Number) e).intValue(); + p++; + } + return r; + } + }; - public static JsonReaderI MAPPER_PRIM_SHORT = new ArraysMapper(null) { - @Override - public short[] convert(Object current) { - int p = 0; - short[] r = new short[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = ((Number) e).shortValue(); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_SHORT = + new ArraysMapper(null) { + @Override + public short[] convert(Object current) { + int p = 0; + short[] r = new short[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = ((Number) e).shortValue(); + return r; + } + }; - public static JsonReaderI MAPPER_SHORT = new ArraysMapper(null) { - @Override - public Short[] convert(Object current) { - int p = 0; - Short[] r = new Short[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - if (e instanceof Short) - r[p] = (Short) e; - else - r[p] = ((Number) e).shortValue(); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_SHORT = + new ArraysMapper(null) { + @Override + public Short[] convert(Object current) { + int p = 0; + Short[] r = new Short[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + if (e instanceof Short) r[p] = (Short) e; + else r[p] = ((Number) e).shortValue(); + p++; + } + return r; + } + }; - public static JsonReaderI MAPPER_PRIM_BYTE = new ArraysMapper(null) { - @Override - public byte[] convert(Object current) { - int p = 0; - byte[] r = new byte[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = ((Number) e).byteValue(); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_BYTE = + new ArraysMapper(null) { + @Override + public byte[] convert(Object current) { + int p = 0; + byte[] r = new byte[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = ((Number) e).byteValue(); + return r; + } + }; - public static JsonReaderI MAPPER_BYTE = new ArraysMapper(null) { - @Override - public Byte[] convert(Object current) { - int p = 0; - Byte[] r = new Byte[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - if (e instanceof Byte) - r[p] = (Byte) e; - else - r[p] = ((Number) e).byteValue(); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_BYTE = + new ArraysMapper(null) { + @Override + public Byte[] convert(Object current) { + int p = 0; + Byte[] r = new Byte[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + if (e instanceof Byte) r[p] = (Byte) e; + else r[p] = ((Number) e).byteValue(); + p++; + } + return r; + } + }; - public static JsonReaderI MAPPER_PRIM_CHAR = new ArraysMapper(null) { - @Override - public char[] convert(Object current) { - int p = 0; - char[] r = new char[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = e.toString().charAt(0); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_CHAR = + new ArraysMapper(null) { + @Override + public char[] convert(Object current) { + int p = 0; + char[] r = new char[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = e.toString().charAt(0); + return r; + } + }; - public static JsonReaderI MAPPER_CHAR = new ArraysMapper(null) { - @Override - public Character[] convert(Object current) { - int p = 0; - Character[] r = new Character[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - r[p] = e.toString().charAt(0); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_CHAR = + new ArraysMapper(null) { + @Override + public Character[] convert(Object current) { + int p = 0; + Character[] r = new Character[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + r[p] = e.toString().charAt(0); + p++; + } + return r; + } + }; - public static JsonReaderI MAPPER_PRIM_LONG = new ArraysMapper(null) { - @Override - public long[] convert(Object current) { - int p = 0; - long[] r = new long[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = ((Number) e).intValue(); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_LONG = + new ArraysMapper(null) { + @Override + public long[] convert(Object current) { + int p = 0; + long[] r = new long[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = ((Number) e).intValue(); + return r; + } + }; - public static JsonReaderI MAPPER_LONG = new ArraysMapper(null) { - @Override - public Long[] convert(Object current) { - int p = 0; - Long[] r = new Long[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - if (e instanceof Float) - r[p] = ((Long) e); - else - r[p] = ((Number) e).longValue(); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_LONG = + new ArraysMapper(null) { + @Override + public Long[] convert(Object current) { + int p = 0; + Long[] r = new Long[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + if (e instanceof Float) r[p] = ((Long) e); + else r[p] = ((Number) e).longValue(); + p++; + } + return r; + } + }; - public static JsonReaderI MAPPER_PRIM_FLOAT = new ArraysMapper(null) { - @Override - public float[] convert(Object current) { - int p = 0; - float[] r = new float[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = ((Number) e).floatValue(); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_FLOAT = + new ArraysMapper(null) { + @Override + public float[] convert(Object current) { + int p = 0; + float[] r = new float[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = ((Number) e).floatValue(); + return r; + } + }; - public static JsonReaderI MAPPER_FLOAT = new ArraysMapper(null) { - @Override - public Float[] convert(Object current) { - int p = 0; - Float[] r = new Float[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - if (e instanceof Float) - r[p] = ((Float) e); - else - r[p] = ((Number) e).floatValue(); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_FLOAT = + new ArraysMapper(null) { + @Override + public Float[] convert(Object current) { + int p = 0; + Float[] r = new Float[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + if (e instanceof Float) r[p] = ((Float) e); + else r[p] = ((Number) e).floatValue(); + p++; + } + return r; + } + }; - public static JsonReaderI MAPPER_PRIM_DOUBLE = new ArraysMapper(null) { - @Override - public double[] convert(Object current) { - int p = 0; - double[] r = new double[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = ((Number) e).doubleValue(); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_DOUBLE = + new ArraysMapper(null) { + @Override + public double[] convert(Object current) { + int p = 0; + double[] r = new double[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = ((Number) e).doubleValue(); + return r; + } + }; - public static JsonReaderI MAPPER_DOUBLE = new ArraysMapper(null) { - @Override - public Double[] convert(Object current) { - int p = 0; - Double[] r = new Double[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - if (e instanceof Double) - r[p] = ((Double) e); - else - r[p] = ((Number) e).doubleValue(); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_DOUBLE = + new ArraysMapper(null) { + @Override + public Double[] convert(Object current) { + int p = 0; + Double[] r = new Double[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + if (e instanceof Double) r[p] = ((Double) e); + else r[p] = ((Number) e).doubleValue(); + p++; + } + return r; + } + }; - public static JsonReaderI MAPPER_PRIM_BOOL = new ArraysMapper(null) { - @Override - public boolean[] convert(Object current) { - int p = 0; - boolean[] r = new boolean[((List) current).size()]; - for (Object e : ((List) current)) - r[p++] = ((Boolean) e).booleanValue(); - return r; - } - }; + public static JsonReaderI MAPPER_PRIM_BOOL = + new ArraysMapper(null) { + @Override + public boolean[] convert(Object current) { + int p = 0; + boolean[] r = new boolean[((List) current).size()]; + for (Object e : ((List) current)) r[p++] = ((Boolean) e).booleanValue(); + return r; + } + }; - public static JsonReaderI MAPPER_BOOL = new ArraysMapper(null) { - @Override - public Boolean[] convert(Object current) { - int p = 0; - Boolean[] r = new Boolean[((List) current).size()]; - for (Object e : ((List) current)) { - if (e == null) - continue; - if (e instanceof Boolean) - r[p] = ((Boolean) e).booleanValue(); - else if (e instanceof Number) - r[p] = ((Number) e).intValue() != 0; - else - throw new RuntimeException("can not convert " + e + " toBoolean"); - p++; - } - return r; - } - }; + public static JsonReaderI MAPPER_BOOL = + new ArraysMapper(null) { + @Override + public Boolean[] convert(Object current) { + int p = 0; + Boolean[] r = new Boolean[((List) current).size()]; + for (Object e : ((List) current)) { + if (e == null) continue; + if (e instanceof Boolean) r[p] = ((Boolean) e).booleanValue(); + else if (e instanceof Number) r[p] = ((Number) e).intValue() != 0; + else throw new RuntimeException("can not convert " + e + " toBoolean"); + p++; + } + return r; + } + }; } diff --git a/json-smart/src/main/java/net/minidev/json/writer/BeansMapper.java b/json-smart/src/main/java/net/minidev/json/writer/BeansMapper.java index 4eb0b54..446b1b7 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/BeansMapper.java +++ b/json-smart/src/main/java/net/minidev/json/writer/BeansMapper.java @@ -19,7 +19,6 @@ import java.lang.reflect.Type; import java.util.Date; import java.util.HashMap; - import net.minidev.asm.Accessor; import net.minidev.asm.BeansAccess; import net.minidev.asm.ConvertDate; @@ -28,126 +27,124 @@ @SuppressWarnings("unchecked") public abstract class BeansMapper extends JsonReaderI { - public BeansMapper(JsonReader base) { - super(base); - } - - public abstract Object getValue(Object current, String key); - - public static class Bean extends JsonReaderI { - final Class clz; - final BeansAccess ba; - final HashMap index; - - public Bean(JsonReader base, Class clz) { - super(base); - this.clz = clz; - this.ba = BeansAccess.get(clz, JSONUtil.JSON_SMART_FIELD_FILTER); - this.index = ba.getMap(); - } - - @Override - public void setValue(Object current, String key, Object value) { - ba.set((T) current, key, value); - // Accessor nfo = index.get(key); - // if (nfo == null) - // throw new RuntimeException("Can not set " + key + " field in " + - // clz); - // value = JSONUtil.convertTo(value, nfo.getType()); - // ba.set((T) current, nfo.getIndex(), value); - } - - public Object getValue(Object current, String key) { - return ba.get((T) current, key); - // Accessor nfo = index.get(key); - // if (nfo == null) - // throw new RuntimeException("Can not set " + key + " field in " + - // clz); - // return ba.get((T) current, nfo.getIndex()); - } - - @Override - public Type getType(String key) { - Accessor nfo = index.get(key); - return nfo.getGenericType(); - } - - @Override - public JsonReaderI startArray(String key) { - Accessor nfo = index.get(key); - if (nfo == null) - throw new RuntimeException("Can not find Array '" + key + "' field in " + clz); - return base.getMapper(nfo.getGenericType()); - } - - @Override - public JsonReaderI startObject(String key) { - Accessor f = index.get(key); - if (f == null) - throw new RuntimeException("Can not find Object '" + key + "' field in " + clz); - return base.getMapper(f.getGenericType()); - } - - @Override - public Object createObject() { - return ba.newInstance(); - } - } - - public static class BeanNoConv extends JsonReaderI { - final Class clz; - final BeansAccess ba; - final HashMap index; - - public BeanNoConv(JsonReader base, Class clz) { - super(base); - this.clz = clz; - this.ba = BeansAccess.get(clz, JSONUtil.JSON_SMART_FIELD_FILTER); - this.index = ba.getMap(); - } - - @Override - public void setValue(Object current, String key, Object value) { - ba.set((T) current, key, value); - } - - public Object getValue(Object current, String key) { - return ba.get((T) current, key); - } - - @Override - public Type getType(String key) { - Accessor nfo = index.get(key); - return nfo.getGenericType(); - } - - @Override - public JsonReaderI startArray(String key) { - Accessor nfo = index.get(key); - if (nfo == null) - throw new RuntimeException("Can not set " + key + " field in " + clz); - return base.getMapper(nfo.getGenericType()); - } - - @Override - public JsonReaderI startObject(String key) { - Accessor f = index.get(key); - if (f == null) - throw new RuntimeException("Can not set " + key + " field in " + clz); - return base.getMapper(f.getGenericType()); - } - - @Override - public Object createObject() { - return ba.newInstance(); - } - } - - public static JsonReaderI MAPPER_DATE = new ArraysMapper(null) { - @Override - public Date convert(Object current) { - return ConvertDate.convertToDate(current); - } - }; - + public BeansMapper(JsonReader base) { + super(base); + } + + public abstract Object getValue(Object current, String key); + + public static class Bean extends JsonReaderI { + final Class clz; + final BeansAccess ba; + final HashMap index; + + public Bean(JsonReader base, Class clz) { + super(base); + this.clz = clz; + this.ba = BeansAccess.get(clz, JSONUtil.JSON_SMART_FIELD_FILTER); + this.index = ba.getMap(); + } + + @Override + public void setValue(Object current, String key, Object value) { + ba.set((T) current, key, value); + // Accessor nfo = index.get(key); + // if (nfo == null) + // throw new RuntimeException("Can not set " + key + " field in " + + // clz); + // value = JSONUtil.convertTo(value, nfo.getType()); + // ba.set((T) current, nfo.getIndex(), value); + } + + public Object getValue(Object current, String key) { + return ba.get((T) current, key); + // Accessor nfo = index.get(key); + // if (nfo == null) + // throw new RuntimeException("Can not set " + key + " field in " + + // clz); + // return ba.get((T) current, nfo.getIndex()); + } + + @Override + public Type getType(String key) { + Accessor nfo = index.get(key); + return nfo.getGenericType(); + } + + @Override + public JsonReaderI startArray(String key) { + Accessor nfo = index.get(key); + if (nfo == null) + throw new RuntimeException("Can not find Array '" + key + "' field in " + clz); + return base.getMapper(nfo.getGenericType()); + } + + @Override + public JsonReaderI startObject(String key) { + Accessor f = index.get(key); + if (f == null) + throw new RuntimeException("Can not find Object '" + key + "' field in " + clz); + return base.getMapper(f.getGenericType()); + } + + @Override + public Object createObject() { + return ba.newInstance(); + } + } + + public static class BeanNoConv extends JsonReaderI { + final Class clz; + final BeansAccess ba; + final HashMap index; + + public BeanNoConv(JsonReader base, Class clz) { + super(base); + this.clz = clz; + this.ba = BeansAccess.get(clz, JSONUtil.JSON_SMART_FIELD_FILTER); + this.index = ba.getMap(); + } + + @Override + public void setValue(Object current, String key, Object value) { + ba.set((T) current, key, value); + } + + public Object getValue(Object current, String key) { + return ba.get((T) current, key); + } + + @Override + public Type getType(String key) { + Accessor nfo = index.get(key); + return nfo.getGenericType(); + } + + @Override + public JsonReaderI startArray(String key) { + Accessor nfo = index.get(key); + if (nfo == null) throw new RuntimeException("Can not set " + key + " field in " + clz); + return base.getMapper(nfo.getGenericType()); + } + + @Override + public JsonReaderI startObject(String key) { + Accessor f = index.get(key); + if (f == null) throw new RuntimeException("Can not set " + key + " field in " + clz); + return base.getMapper(f.getGenericType()); + } + + @Override + public Object createObject() { + return ba.newInstance(); + } + } + + public static JsonReaderI MAPPER_DATE = + new ArraysMapper(null) { + @Override + public Date convert(Object current) { + return ConvertDate.convertToDate(current); + } + }; } diff --git a/json-smart/src/main/java/net/minidev/json/writer/CollectionMapper.java b/json-smart/src/main/java/net/minidev/json/writer/CollectionMapper.java index 09e2403..83b7821 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/CollectionMapper.java +++ b/json-smart/src/main/java/net/minidev/json/writer/CollectionMapper.java @@ -19,7 +19,6 @@ import java.lang.reflect.Type; import java.util.List; import java.util.Map; - import net.minidev.asm.BeansAccess; import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; @@ -27,226 +26,212 @@ public class CollectionMapper { - public static class MapType extends JsonReaderI { - final ParameterizedType type; - final Class rawClass; - final Class instance; - final BeansAccess ba; - - final Type keyType; - final Type valueType; - - final Class keyClass; - final Class valueClass; - - JsonReaderI subMapper; - - public MapType(JsonReader base, ParameterizedType type) { - super(base); - this.type = type; - this.rawClass = (Class) type.getRawType(); - if (rawClass.isInterface()) - instance = JSONObject.class; - else - instance = rawClass; - ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); - - keyType = type.getActualTypeArguments()[0]; - valueType = type.getActualTypeArguments()[1]; - if (keyType instanceof Class) - keyClass = (Class) keyType; - else - keyClass = (Class) ((ParameterizedType) keyType).getRawType(); - if (valueType instanceof Class) - valueClass = (Class) valueType; - else - valueClass = (Class) ((ParameterizedType) valueType).getRawType(); - } - - @Override - public Object createObject() { - try { - return instance.newInstance(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return null; - } - - @Override - public JsonReaderI startArray(String key) { - if (subMapper == null) - subMapper = base.getMapper(valueType); - return subMapper; - } - - @Override - public JsonReaderI startObject(String key) { - if (subMapper == null) - subMapper = base.getMapper(valueType); - return subMapper; - } - - @SuppressWarnings("unchecked") - @Override - public void setValue(Object current, String key, Object value) { - ((Map) current).put(JSONUtil.convertToX(key, keyClass), - JSONUtil.convertToX(value, valueClass)); - } - - @SuppressWarnings("unchecked") - @Override - public Object getValue(Object current, String key) { - return ((Map) current).get(JSONUtil.convertToX(key, keyClass)); - } - - @Override - public Type getType(String key) { - return type; - } - }; - - public static class MapClass extends JsonReaderI { - final Class type; - final Class instance; - final BeansAccess ba; - - JsonReaderI subMapper; - - public MapClass(JsonReader base, Class type) { - super(base); - this.type = type; - if (type.isInterface()) - this.instance = JSONObject.class; - else - this.instance = type; - this.ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); - } - - @Override - public Object createObject() { - return ba.newInstance(); - } - - @Override - public JsonReaderI startArray(String key) { - return base.DEFAULT ; // _ARRAY - } - - @Override - public JsonReaderI startObject(String key) { - return base.DEFAULT; // _MAP - } - - @SuppressWarnings("unchecked") - @Override - public void setValue(Object current, String key, Object value) { - ((Map) current).put(key, value); - } - - @SuppressWarnings("unchecked") - @Override - public Object getValue(Object current, String key) { - return ((Map) current).get(key); - } - - @Override - public Type getType(String key) { - return type; - } - }; - - public static class ListType extends JsonReaderI { - final ParameterizedType type; - final Class rawClass; - final Class instance; - final BeansAccess ba; - - final Type valueType; - final Class valueClass; - - JsonReaderI subMapper; - - public ListType(JsonReader base, ParameterizedType type) { - super(base); - this.type = type; - this.rawClass = (Class) type.getRawType(); - if (rawClass.isInterface()) - instance = JSONArray.class; - else - instance = rawClass; - ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); // NEW - valueType = type.getActualTypeArguments()[0]; - if (valueType instanceof Class) - valueClass = (Class) valueType; - else - valueClass = (Class) ((ParameterizedType) valueType).getRawType(); - } - - @Override - public Object createArray() { - return ba.newInstance(); - } - - @Override - public JsonReaderI startArray(String key) { - if (subMapper == null) - subMapper = base.getMapper(type.getActualTypeArguments()[0]); - return subMapper; - } - - @Override - public JsonReaderI startObject(String key) { - if (subMapper == null) - subMapper = base.getMapper(type.getActualTypeArguments()[0]); - return subMapper; - } - - @SuppressWarnings("unchecked") - @Override - public void addValue(Object current, Object value) { - ((List) current).add(JSONUtil.convertToX(value, valueClass)); - } - }; - - public static class ListClass extends JsonReaderI { - final Class type; - final Class instance; - final BeansAccess ba; - - JsonReaderI subMapper; - - public ListClass(JsonReader base, Class clazz) { - super(base); - this.type = clazz; - if (clazz.isInterface()) - instance = JSONArray.class; - else - instance = clazz; - ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); - } - - @Override - public Object createArray() { - return ba.newInstance(); - } - - @Override - public JsonReaderI startArray(String key) { - return base.DEFAULT;// _ARRAY; - } - - @Override - public JsonReaderI startObject(String key) { - return base.DEFAULT;// _MAP; - } - - @SuppressWarnings("unchecked") - @Override - public void addValue(Object current, Object value) { - ((List) current).add(value); - } - }; + public static class MapType extends JsonReaderI { + final ParameterizedType type; + final Class rawClass; + final Class instance; + final BeansAccess ba; + + final Type keyType; + final Type valueType; + + final Class keyClass; + final Class valueClass; + + JsonReaderI subMapper; + + public MapType(JsonReader base, ParameterizedType type) { + super(base); + this.type = type; + this.rawClass = (Class) type.getRawType(); + if (rawClass.isInterface()) instance = JSONObject.class; + else instance = rawClass; + ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); + + keyType = type.getActualTypeArguments()[0]; + valueType = type.getActualTypeArguments()[1]; + if (keyType instanceof Class) keyClass = (Class) keyType; + else keyClass = (Class) ((ParameterizedType) keyType).getRawType(); + if (valueType instanceof Class) valueClass = (Class) valueType; + else valueClass = (Class) ((ParameterizedType) valueType).getRawType(); + } + + @Override + public Object createObject() { + try { + return instance.newInstance(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + @Override + public JsonReaderI startArray(String key) { + if (subMapper == null) subMapper = base.getMapper(valueType); + return subMapper; + } + + @Override + public JsonReaderI startObject(String key) { + if (subMapper == null) subMapper = base.getMapper(valueType); + return subMapper; + } + + @SuppressWarnings("unchecked") + @Override + public void setValue(Object current, String key, Object value) { + ((Map) current) + .put(JSONUtil.convertToX(key, keyClass), JSONUtil.convertToX(value, valueClass)); + } + + @SuppressWarnings("unchecked") + @Override + public Object getValue(Object current, String key) { + return ((Map) current).get(JSONUtil.convertToX(key, keyClass)); + } + + @Override + public Type getType(String key) { + return type; + } + } + ; + + public static class MapClass extends JsonReaderI { + final Class type; + final Class instance; + final BeansAccess ba; + + JsonReaderI subMapper; + + public MapClass(JsonReader base, Class type) { + super(base); + this.type = type; + if (type.isInterface()) this.instance = JSONObject.class; + else this.instance = type; + this.ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); + } + + @Override + public Object createObject() { + return ba.newInstance(); + } + + @Override + public JsonReaderI startArray(String key) { + return base.DEFAULT; // _ARRAY + } + + @Override + public JsonReaderI startObject(String key) { + return base.DEFAULT; // _MAP + } + + @SuppressWarnings("unchecked") + @Override + public void setValue(Object current, String key, Object value) { + ((Map) current).put(key, value); + } + + @SuppressWarnings("unchecked") + @Override + public Object getValue(Object current, String key) { + return ((Map) current).get(key); + } + + @Override + public Type getType(String key) { + return type; + } + } + ; + + public static class ListType extends JsonReaderI { + final ParameterizedType type; + final Class rawClass; + final Class instance; + final BeansAccess ba; + + final Type valueType; + final Class valueClass; + + JsonReaderI subMapper; + + public ListType(JsonReader base, ParameterizedType type) { + super(base); + this.type = type; + this.rawClass = (Class) type.getRawType(); + if (rawClass.isInterface()) instance = JSONArray.class; + else instance = rawClass; + ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); // NEW + valueType = type.getActualTypeArguments()[0]; + if (valueType instanceof Class) valueClass = (Class) valueType; + else valueClass = (Class) ((ParameterizedType) valueType).getRawType(); + } + + @Override + public Object createArray() { + return ba.newInstance(); + } + + @Override + public JsonReaderI startArray(String key) { + if (subMapper == null) subMapper = base.getMapper(type.getActualTypeArguments()[0]); + return subMapper; + } + + @Override + public JsonReaderI startObject(String key) { + if (subMapper == null) subMapper = base.getMapper(type.getActualTypeArguments()[0]); + return subMapper; + } + + @SuppressWarnings("unchecked") + @Override + public void addValue(Object current, Object value) { + ((List) current).add(JSONUtil.convertToX(value, valueClass)); + } + } + ; + + public static class ListClass extends JsonReaderI { + final Class type; + final Class instance; + final BeansAccess ba; + + JsonReaderI subMapper; + + public ListClass(JsonReader base, Class clazz) { + super(base); + this.type = clazz; + if (clazz.isInterface()) instance = JSONArray.class; + else instance = clazz; + ba = BeansAccess.get(instance, JSONUtil.JSON_SMART_FIELD_FILTER); + } + + @Override + public Object createArray() { + return ba.newInstance(); + } + + @Override + public JsonReaderI startArray(String key) { + return base.DEFAULT; // _ARRAY; + } + + @Override + public JsonReaderI startObject(String key) { + return base.DEFAULT; // _MAP; + } + + @SuppressWarnings("unchecked") + @Override + public void addValue(Object current, Object value) { + ((List) current).add(value); + } + } + ; } diff --git a/json-smart/src/main/java/net/minidev/json/writer/CompessorMapper.java b/json-smart/src/main/java/net/minidev/json/writer/CompessorMapper.java index c23edab..0140077 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/CompessorMapper.java +++ b/json-smart/src/main/java/net/minidev/json/writer/CompessorMapper.java @@ -16,203 +16,195 @@ * limitations under the License. */ import java.io.IOException; - import net.minidev.json.JSONStyle; import net.minidev.json.JSONValue; public class CompessorMapper extends JsonReaderI { - private Appendable out; - private JSONStyle compression; - private Boolean _isObj; - private boolean needSep = false; - private boolean isOpen = false; - private boolean isClosed = false; - - // private boolean isRoot = false; - - private boolean isArray() { - return _isObj == Boolean.FALSE; - } - - private boolean isObject() { - return _isObj == Boolean.TRUE; - } - - private boolean isCompressor(Object obj) { - return obj instanceof CompessorMapper; - } - - public CompessorMapper(JsonReader base, Appendable out, JSONStyle compression) { - this(base, out, compression, null); - // isRoot = true; - } - - public CompessorMapper(JsonReader base, Appendable out, JSONStyle compression, Boolean isObj) { - super(base); - this.out = out; - this.compression = compression; - this._isObj = isObj; - // System.out.println("new CompressorMapper isObj:" + isObj); - } - - @Override - public JsonReaderI startObject(String key) throws IOException { - open(this); - startKey(key); - // System.out.println("startObject " + key); - CompessorMapper r = new CompessorMapper(base, out, compression, true); - open(r); - return r; - } - - @Override - public JsonReaderI startArray(String key) throws IOException { - open(this); - startKey(key); - // System.out.println("startArray " + key); - CompessorMapper r = new CompessorMapper(base, out, compression, false); - open(r); - return r; - } - - private void startKey(String key) throws IOException { - addComma(); - // if (key == null) - // return; - if (isArray()) - return; - if (!compression.mustProtectKey(key)) - out.append(key); - else { - out.append('"'); - JSONValue.escape(key, out, compression); - out.append('"'); - } - out.append(':'); - } - - @Override - public void setValue(Object current, String key, Object value) throws IOException { - // System.out.println("setValue(" + key + "," + value + ")"); - // if compressor => data already be written - if (isCompressor(value)) { - addComma(); - return; - } - startKey(key); - writeValue(value); - } - - @Override - public void addValue(Object current, Object value) throws IOException { - // System.out.println("add value" + value); - // if (!isCompressor(value)) - addComma(); - writeValue(value); - } - - private void addComma() throws IOException { - if (needSep) { - out.append(','); - // needSep = false; - } else { - needSep = true; - } - } - - private void writeValue(Object value) throws IOException { - if (value instanceof String) { - compression.writeString(out, (String) value); -// -// if (!compression.mustProtectValue((String) value)) -// out.append((String) value); -// else { -// out.append('"'); -// JSONValue.escape((String) value, out, compression); -// out.append('"'); -// } - // needSep = true; - } else { - if (isCompressor(value)) { - close(value); - // needSep = true; - } else { - JSONValue.writeJSONString(value, out, compression); - // needSep = true; - } - } - } - - @Override - public Object createObject() { - // System.out.println("createObject"); - this._isObj = true; - try { - open(this); - } catch (Exception e) { - } - // if (this.isUnknow() && isRoot) { // && isRoot - // this._isObj = true; - // try { - // out.append('{'); // 1 - // } catch (Exception e) { - // } - // } - return this; - } - - @Override - public Object createArray() { - // System.out.println("createArray"); - this._isObj = false; - try { - open(this); - } catch (Exception e) { - } - return this; - } - - public CompessorMapper convert(Object current) { - try { - close(current); - return this; - } catch (Exception e) { - return this; - } - } - - private void close(Object obj) throws IOException { - if (!isCompressor(obj)) - return; - if (((CompessorMapper) obj).isClosed) - return; - ((CompessorMapper) obj).isClosed = true; - if (((CompessorMapper) obj).isObject()) { - // System.out.println("convert }"); - out.append('}'); - needSep = true; - } else if (((CompessorMapper) obj).isArray()) { - // System.out.println("convert ]"); - out.append(']'); - needSep = true; - } - } - - private void open(Object obj) throws IOException { - if (!isCompressor(obj)) - return; - if (((CompessorMapper) obj).isOpen) - return; - ((CompessorMapper) obj).isOpen = true; - if (((CompessorMapper) obj).isObject()) { - // System.out.println("open {"); - out.append('{'); - needSep = false; - } else if (((CompessorMapper) obj).isArray()) { - // System.out.println("open ["); - out.append('['); - needSep = false; - } - } - + private Appendable out; + private JSONStyle compression; + private Boolean _isObj; + private boolean needSep = false; + private boolean isOpen = false; + private boolean isClosed = false; + + // private boolean isRoot = false; + + private boolean isArray() { + return _isObj == Boolean.FALSE; + } + + private boolean isObject() { + return _isObj == Boolean.TRUE; + } + + private boolean isCompressor(Object obj) { + return obj instanceof CompessorMapper; + } + + public CompessorMapper(JsonReader base, Appendable out, JSONStyle compression) { + this(base, out, compression, null); + // isRoot = true; + } + + public CompessorMapper(JsonReader base, Appendable out, JSONStyle compression, Boolean isObj) { + super(base); + this.out = out; + this.compression = compression; + this._isObj = isObj; + // System.out.println("new CompressorMapper isObj:" + isObj); + } + + @Override + public JsonReaderI startObject(String key) throws IOException { + open(this); + startKey(key); + // System.out.println("startObject " + key); + CompessorMapper r = new CompessorMapper(base, out, compression, true); + open(r); + return r; + } + + @Override + public JsonReaderI startArray(String key) throws IOException { + open(this); + startKey(key); + // System.out.println("startArray " + key); + CompessorMapper r = new CompessorMapper(base, out, compression, false); + open(r); + return r; + } + + private void startKey(String key) throws IOException { + addComma(); + // if (key == null) + // return; + if (isArray()) return; + if (!compression.mustProtectKey(key)) out.append(key); + else { + out.append('"'); + JSONValue.escape(key, out, compression); + out.append('"'); + } + out.append(':'); + } + + @Override + public void setValue(Object current, String key, Object value) throws IOException { + // System.out.println("setValue(" + key + "," + value + ")"); + // if compressor => data already be written + if (isCompressor(value)) { + addComma(); + return; + } + startKey(key); + writeValue(value); + } + + @Override + public void addValue(Object current, Object value) throws IOException { + // System.out.println("add value" + value); + // if (!isCompressor(value)) + addComma(); + writeValue(value); + } + + private void addComma() throws IOException { + if (needSep) { + out.append(','); + // needSep = false; + } else { + needSep = true; + } + } + + private void writeValue(Object value) throws IOException { + if (value instanceof String) { + compression.writeString(out, (String) value); + // + // if (!compression.mustProtectValue((String) value)) + // out.append((String) value); + // else { + // out.append('"'); + // JSONValue.escape((String) value, out, compression); + // out.append('"'); + // } + // needSep = true; + } else { + if (isCompressor(value)) { + close(value); + // needSep = true; + } else { + JSONValue.writeJSONString(value, out, compression); + // needSep = true; + } + } + } + + @Override + public Object createObject() { + // System.out.println("createObject"); + this._isObj = true; + try { + open(this); + } catch (Exception e) { + } + // if (this.isUnknow() && isRoot) { // && isRoot + // this._isObj = true; + // try { + // out.append('{'); // 1 + // } catch (Exception e) { + // } + // } + return this; + } + + @Override + public Object createArray() { + // System.out.println("createArray"); + this._isObj = false; + try { + open(this); + } catch (Exception e) { + } + return this; + } + + public CompessorMapper convert(Object current) { + try { + close(current); + return this; + } catch (Exception e) { + return this; + } + } + + private void close(Object obj) throws IOException { + if (!isCompressor(obj)) return; + if (((CompessorMapper) obj).isClosed) return; + ((CompessorMapper) obj).isClosed = true; + if (((CompessorMapper) obj).isObject()) { + // System.out.println("convert }"); + out.append('}'); + needSep = true; + } else if (((CompessorMapper) obj).isArray()) { + // System.out.println("convert ]"); + out.append(']'); + needSep = true; + } + } + + private void open(Object obj) throws IOException { + if (!isCompressor(obj)) return; + if (((CompessorMapper) obj).isOpen) return; + ((CompessorMapper) obj).isOpen = true; + if (((CompessorMapper) obj).isObject()) { + // System.out.println("open {"); + out.append('{'); + needSep = false; + } else if (((CompessorMapper) obj).isArray()) { + // System.out.println("open ["); + out.append('['); + needSep = false; + } + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/DefaultMapper.java b/json-smart/src/main/java/net/minidev/json/writer/DefaultMapper.java index a3cf49d..976b38a 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/DefaultMapper.java +++ b/json-smart/src/main/java/net/minidev/json/writer/DefaultMapper.java @@ -18,46 +18,45 @@ import net.minidev.json.JSONArray; import net.minidev.json.JSONAwareEx; import net.minidev.json.JSONObject; + /** * Simple Reader Class for generic Map - * - * @author uriel * + * @author uriel * @param */ public class DefaultMapper extends JsonReaderI { - protected DefaultMapper(JsonReader base) { - super(base); - } - - @Override - public JsonReaderI startObject(String key) { - return base.DEFAULT; - } - - @Override - public JsonReaderI startArray(String key) { - return base.DEFAULT; - } - - @Override - public Object createObject() { - return new JSONObject(); - } - - @Override - public Object createArray() { - return new JSONArray(); - } - - @Override - public void setValue(Object current, String key, Object value) { - ((JSONObject) current).put(key, value); - } - - @Override - public void addValue(Object current, Object value) { - ((JSONArray) current).add(value); - } - + protected DefaultMapper(JsonReader base) { + super(base); + } + + @Override + public JsonReaderI startObject(String key) { + return base.DEFAULT; + } + + @Override + public JsonReaderI startArray(String key) { + return base.DEFAULT; + } + + @Override + public Object createObject() { + return new JSONObject(); + } + + @Override + public Object createArray() { + return new JSONArray(); + } + + @Override + public void setValue(Object current, String key, Object value) { + ((JSONObject) current).put(key, value); + } + + @Override + public void addValue(Object current, Object value) { + ((JSONArray) current).add(value); + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperCollection.java b/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperCollection.java index 975df91..e0c5217 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperCollection.java +++ b/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperCollection.java @@ -20,55 +20,55 @@ import java.util.Map; public class DefaultMapperCollection extends JsonReaderI { - Class clz; - //? extends Collection - public DefaultMapperCollection(JsonReader base, Class clz) { - super(base); - this.clz = clz; - } + Class clz; - // public static AMapper DEFAULT = new - // DefaultMapperCollection(); - @Override - public JsonReaderI startObject(String key) { - return this; - } + // ? extends Collection + public DefaultMapperCollection(JsonReader base, Class clz) { + super(base); + this.clz = clz; + } - @Override - public JsonReaderI startArray(String key) { - return this; - } + // public static AMapper DEFAULT = new + // DefaultMapperCollection(); + @Override + public JsonReaderI startObject(String key) { + return this; + } - @Override - public Object createObject() { - try { - Constructor c = clz.getConstructor(); - return c.newInstance(); - } catch (Exception e) { - return null; - } - } + @Override + public JsonReaderI startArray(String key) { + return this; + } - @Override - public Object createArray() { - try { - Constructor c = clz.getConstructor(); - return c.newInstance(); - } catch (Exception e) { - return null; - } - } + @Override + public Object createObject() { + try { + Constructor c = clz.getConstructor(); + return c.newInstance(); + } catch (Exception e) { + return null; + } + } - @SuppressWarnings({ "unchecked"}) - @Override - public void setValue(Object current, String key, Object value) { - ((Map) current).put(key, value); - } + @Override + public Object createArray() { + try { + Constructor c = clz.getConstructor(); + return c.newInstance(); + } catch (Exception e) { + return null; + } + } - @SuppressWarnings("unchecked") - @Override - public void addValue(Object current, Object value) { - ((List) current).add(value); - } + @SuppressWarnings({"unchecked"}) + @Override + public void setValue(Object current, String key, Object value) { + ((Map) current).put(key, value); + } + @SuppressWarnings("unchecked") + @Override + public void addValue(Object current, Object value) { + ((List) current).add(value); + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperOrdered.java b/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperOrdered.java index 5cca8b2..75b931a 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperOrdered.java +++ b/json-smart/src/main/java/net/minidev/json/writer/DefaultMapperOrdered.java @@ -17,42 +17,42 @@ */ import java.util.LinkedHashMap; import java.util.Map; - import net.minidev.json.JSONArray; import net.minidev.json.JSONAwareEx; public class DefaultMapperOrdered extends JsonReaderI { - protected DefaultMapperOrdered(JsonReader base) { - super(base); - }; - - @Override - public JsonReaderI startObject(String key) { - return base.DEFAULT_ORDERED; - } - - @Override - public JsonReaderI startArray(String key) { - return base.DEFAULT_ORDERED; - } - - @SuppressWarnings("unchecked") - public void setValue(Object current, String key, Object value) { - ((Map) current).put(key, value); - } - - @Override - public Object createObject() { - return new LinkedHashMap(); - } - - @Override - public void addValue(Object current, Object value) { - ((JSONArray) current).add(value); - } - - @Override - public Object createArray() { - return new JSONArray(); - } + protected DefaultMapperOrdered(JsonReader base) { + super(base); + } + ; + + @Override + public JsonReaderI startObject(String key) { + return base.DEFAULT_ORDERED; + } + + @Override + public JsonReaderI startArray(String key) { + return base.DEFAULT_ORDERED; + } + + @SuppressWarnings("unchecked") + public void setValue(Object current, String key, Object value) { + ((Map) current).put(key, value); + } + + @Override + public Object createObject() { + return new LinkedHashMap(); + } + + @Override + public void addValue(Object current, Object value) { + ((JSONArray) current).add(value); + } + + @Override + public Object createArray() { + return new JSONArray(); + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/FakeMapper.java b/json-smart/src/main/java/net/minidev/json/writer/FakeMapper.java index 504df3b..c0b8b31 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/FakeMapper.java +++ b/json-smart/src/main/java/net/minidev/json/writer/FakeMapper.java @@ -1,6 +1,5 @@ package net.minidev.json.writer; - /* * Copyright 2011-2024 JSON-SMART authors * @@ -18,37 +17,35 @@ */ public class FakeMapper extends JsonReaderI { - private FakeMapper() { - super(null); - } - - public static JsonReaderI DEFAULT = new FakeMapper(); - - @Override - public JsonReaderI startObject(String key) { - return this; - } - - @Override - public JsonReaderI startArray(String key) { - return this; - } - - @Override - public void setValue(Object current, String key, Object value) { - } - - @Override - public void addValue(Object current, Object value) { - } - - @Override - public Object createObject() { - return null; - } - - @Override - public Object createArray() { - return null; - } + private FakeMapper() { + super(null); + } + + public static JsonReaderI DEFAULT = new FakeMapper(); + + @Override + public JsonReaderI startObject(String key) { + return this; + } + + @Override + public JsonReaderI startArray(String key) { + return this; + } + + @Override + public void setValue(Object current, String key, Object value) {} + + @Override + public void addValue(Object current, Object value) {} + + @Override + public Object createObject() { + return null; + } + + @Override + public Object createArray() { + return null; + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/JsonReader.java b/json-smart/src/main/java/net/minidev/json/writer/JsonReader.java index 982b507..ec6b725 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/JsonReader.java +++ b/json-smart/src/main/java/net/minidev/json/writer/JsonReader.java @@ -21,135 +21,121 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; - import net.minidev.json.JSONArray; import net.minidev.json.JSONAware; import net.minidev.json.JSONAwareEx; import net.minidev.json.JSONObject; public class JsonReader { - private final ConcurrentHashMap> cache; - - public JsonReaderI DEFAULT; - public JsonReaderI DEFAULT_ORDERED; - - public JsonReader() { - cache = new ConcurrentHashMap>(100); - - cache.put(Date.class, BeansMapper.MAPPER_DATE); - - cache.put(int[].class, ArraysMapper.MAPPER_PRIM_INT); - cache.put(Integer[].class, ArraysMapper.MAPPER_INT); - - cache.put(short[].class, ArraysMapper.MAPPER_PRIM_INT); - cache.put(Short[].class, ArraysMapper.MAPPER_INT); - - cache.put(long[].class, ArraysMapper.MAPPER_PRIM_LONG); - cache.put(Long[].class, ArraysMapper.MAPPER_LONG); - - cache.put(byte[].class, ArraysMapper.MAPPER_PRIM_BYTE); - cache.put(Byte[].class, ArraysMapper.MAPPER_BYTE); - - cache.put(char[].class, ArraysMapper.MAPPER_PRIM_CHAR); - cache.put(Character[].class, ArraysMapper.MAPPER_CHAR); - - cache.put(float[].class, ArraysMapper.MAPPER_PRIM_FLOAT); - cache.put(Float[].class, ArraysMapper.MAPPER_FLOAT); - - cache.put(double[].class, ArraysMapper.MAPPER_PRIM_DOUBLE); - cache.put(Double[].class, ArraysMapper.MAPPER_DOUBLE); - - cache.put(boolean[].class, ArraysMapper.MAPPER_PRIM_BOOL); - cache.put(Boolean[].class, ArraysMapper.MAPPER_BOOL); - - this.DEFAULT = new DefaultMapper(this); - this.DEFAULT_ORDERED = new DefaultMapperOrdered(this); - - cache.put(JSONAwareEx.class, this.DEFAULT); - cache.put(JSONAware.class, this.DEFAULT); - cache.put(JSONArray.class, this.DEFAULT); - cache.put(JSONObject.class, this.DEFAULT); - } - - /** - * remap field name in custom classes - * - * @param fromJson - * field name in json - * @param toJava - * field name in Java - * @since 2.1.1 - */ - public void remapField(Class type, String fromJson, String toJava) { - JsonReaderI map = this.getMapper(type); - if (!(map instanceof MapperRemapped)) { - map = new MapperRemapped(map); - registerReader(type, map); - } - ((MapperRemapped) map).renameField(fromJson, toJava); - } - - public void registerReader(Class type, JsonReaderI mapper) { - cache.put(type, mapper); - } - - @SuppressWarnings("unchecked") - public JsonReaderI getMapper(Type type) { - if (type instanceof ParameterizedType) - return getMapper((ParameterizedType) type); - return getMapper((Class) type); - } - - /** - * Get the corresponding mapper Class, or create it on first call - * - * @param type - * to be map - */ - public JsonReaderI getMapper(Class type) { - // look for cached Mapper - @SuppressWarnings("unchecked") - JsonReaderI map = (JsonReaderI) cache.get(type); - if (map != null) - return map; - /* - * Special handle - */ - if (type instanceof Class) { - if (Map.class.isAssignableFrom(type)) - map = new DefaultMapperCollection(this, type); - else if (List.class.isAssignableFrom(type)) - map = new DefaultMapperCollection(this, type); - if (map != null) { - cache.put(type, map); - return map; - } - } - - if (type.isArray()) - map = new ArraysMapper.GenericMapper(this, type); - else if (List.class.isAssignableFrom(type)) - map = new CollectionMapper.ListClass(this, type); - else if (Map.class.isAssignableFrom(type)) - map = new CollectionMapper.MapClass(this, type); - else - // use bean class - map = new BeansMapper.Bean(this, type); - cache.putIfAbsent(type, map); - return map; - } - - @SuppressWarnings("unchecked") - public JsonReaderI getMapper(ParameterizedType type) { - JsonReaderI map = (JsonReaderI) cache.get(type); - if (map != null) - return map; - Class clz = (Class) type.getRawType(); - if (List.class.isAssignableFrom(clz)) - map = new CollectionMapper.ListType(this, type); - else if (Map.class.isAssignableFrom(clz)) - map = new CollectionMapper.MapType(this, type); - cache.putIfAbsent(type, map); - return map; - } + private final ConcurrentHashMap> cache; + + public JsonReaderI DEFAULT; + public JsonReaderI DEFAULT_ORDERED; + + public JsonReader() { + cache = new ConcurrentHashMap>(100); + + cache.put(Date.class, BeansMapper.MAPPER_DATE); + + cache.put(int[].class, ArraysMapper.MAPPER_PRIM_INT); + cache.put(Integer[].class, ArraysMapper.MAPPER_INT); + + cache.put(short[].class, ArraysMapper.MAPPER_PRIM_INT); + cache.put(Short[].class, ArraysMapper.MAPPER_INT); + + cache.put(long[].class, ArraysMapper.MAPPER_PRIM_LONG); + cache.put(Long[].class, ArraysMapper.MAPPER_LONG); + + cache.put(byte[].class, ArraysMapper.MAPPER_PRIM_BYTE); + cache.put(Byte[].class, ArraysMapper.MAPPER_BYTE); + + cache.put(char[].class, ArraysMapper.MAPPER_PRIM_CHAR); + cache.put(Character[].class, ArraysMapper.MAPPER_CHAR); + + cache.put(float[].class, ArraysMapper.MAPPER_PRIM_FLOAT); + cache.put(Float[].class, ArraysMapper.MAPPER_FLOAT); + + cache.put(double[].class, ArraysMapper.MAPPER_PRIM_DOUBLE); + cache.put(Double[].class, ArraysMapper.MAPPER_DOUBLE); + + cache.put(boolean[].class, ArraysMapper.MAPPER_PRIM_BOOL); + cache.put(Boolean[].class, ArraysMapper.MAPPER_BOOL); + + this.DEFAULT = new DefaultMapper(this); + this.DEFAULT_ORDERED = new DefaultMapperOrdered(this); + + cache.put(JSONAwareEx.class, this.DEFAULT); + cache.put(JSONAware.class, this.DEFAULT); + cache.put(JSONArray.class, this.DEFAULT); + cache.put(JSONObject.class, this.DEFAULT); + } + + /** + * remap field name in custom classes + * + * @param fromJson field name in json + * @param toJava field name in Java + * @since 2.1.1 + */ + public void remapField(Class type, String fromJson, String toJava) { + JsonReaderI map = this.getMapper(type); + if (!(map instanceof MapperRemapped)) { + map = new MapperRemapped(map); + registerReader(type, map); + } + ((MapperRemapped) map).renameField(fromJson, toJava); + } + + public void registerReader(Class type, JsonReaderI mapper) { + cache.put(type, mapper); + } + + @SuppressWarnings("unchecked") + public JsonReaderI getMapper(Type type) { + if (type instanceof ParameterizedType) return getMapper((ParameterizedType) type); + return getMapper((Class) type); + } + + /** + * Get the corresponding mapper Class, or create it on first call + * + * @param type to be map + */ + public JsonReaderI getMapper(Class type) { + // look for cached Mapper + @SuppressWarnings("unchecked") + JsonReaderI map = (JsonReaderI) cache.get(type); + if (map != null) return map; + /* + * Special handle + */ + if (type instanceof Class) { + if (Map.class.isAssignableFrom(type)) map = new DefaultMapperCollection(this, type); + else if (List.class.isAssignableFrom(type)) map = new DefaultMapperCollection(this, type); + if (map != null) { + cache.put(type, map); + return map; + } + } + + if (type.isArray()) map = new ArraysMapper.GenericMapper(this, type); + else if (List.class.isAssignableFrom(type)) map = new CollectionMapper.ListClass(this, type); + else if (Map.class.isAssignableFrom(type)) map = new CollectionMapper.MapClass(this, type); + else + // use bean class + map = new BeansMapper.Bean(this, type); + cache.putIfAbsent(type, map); + return map; + } + + @SuppressWarnings("unchecked") + public JsonReaderI getMapper(ParameterizedType type) { + JsonReaderI map = (JsonReaderI) cache.get(type); + if (map != null) return map; + Class clz = (Class) type.getRawType(); + if (List.class.isAssignableFrom(clz)) map = new CollectionMapper.ListType(this, type); + else if (Map.class.isAssignableFrom(clz)) map = new CollectionMapper.MapType(this, type); + cache.putIfAbsent(type, map); + return map; + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/JsonReaderI.java b/json-smart/src/main/java/net/minidev/json/writer/JsonReaderI.java index b6a529d..a456e5c 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/JsonReaderI.java +++ b/json-smart/src/main/java/net/minidev/json/writer/JsonReaderI.java @@ -17,94 +17,88 @@ */ import java.io.IOException; import java.lang.reflect.Type; - import net.minidev.json.parser.ParseException; /** * Default datatype mapper use by Json-smart ton store data. - * - * @author uriel Chemouni * + * @author uriel Chemouni * @param result type */ public abstract class JsonReaderI { - public final JsonReader base; + public final JsonReader base; - /** - * Reader can be link to the JsonReader Base - * - * @param base parent reader - */ - public JsonReaderI(JsonReader base) { - this.base = base; - } + /** + * Reader can be link to the JsonReader Base + * + * @param base parent reader + */ + public JsonReaderI(JsonReader base) { + this.base = base; + } - private static String ERR_MSG = "Invalid or non Implemented status"; + private static String ERR_MSG = "Invalid or non Implemented status"; - /** - * called when json-smart parser meet an object key - * @param key key name - */ - public JsonReaderI startObject(String key) throws ParseException, IOException { - throw new RuntimeException(ERR_MSG + " startObject(String key) in " + this.getClass() + " key=" + key); - } + /** + * called when json-smart parser meet an object key + * + * @param key key name + */ + public JsonReaderI startObject(String key) throws ParseException, IOException { + throw new RuntimeException( + ERR_MSG + " startObject(String key) in " + this.getClass() + " key=" + key); + } - /** - * called when json-smart parser start an array. - * - * @param key the destination key name, or null. - */ - public JsonReaderI startArray(String key) throws ParseException, IOException { - throw new RuntimeException(ERR_MSG + " startArray in " + this.getClass() + " key=" + key); - } + /** + * called when json-smart parser start an array. + * + * @param key the destination key name, or null. + */ + public JsonReaderI startArray(String key) throws ParseException, IOException { + throw new RuntimeException(ERR_MSG + " startArray in " + this.getClass() + " key=" + key); + } - /** - * called when json-smart done parsing a value - */ - public void setValue(Object current, String key, Object value) throws ParseException, IOException { - throw new RuntimeException(ERR_MSG + " setValue in " + this.getClass() + " key=" + key); - } + /** called when json-smart done parsing a value */ + public void setValue(Object current, String key, Object value) + throws ParseException, IOException { + throw new RuntimeException(ERR_MSG + " setValue in " + this.getClass() + " key=" + key); + } - /** - * ------------- - */ - public Object getValue(Object current, String key) { - throw new RuntimeException(ERR_MSG + " getValue(Object current, String key) in " + this.getClass() + " key=" + key); - } + /** ------------- */ + public Object getValue(Object current, String key) { + throw new RuntimeException( + ERR_MSG + " getValue(Object current, String key) in " + this.getClass() + " key=" + key); + } - // Object current, - public Type getType(String key) { - throw new RuntimeException(ERR_MSG + " getType(String key) in " + this.getClass() + " key=" + key); - } + // Object current, + public Type getType(String key) { + throw new RuntimeException( + ERR_MSG + " getType(String key) in " + this.getClass() + " key=" + key); + } - /** - * add a value in an array json object. - */ - public void addValue(Object current, Object value) throws ParseException, IOException { - throw new RuntimeException(ERR_MSG + " addValue(Object current, Object value) in " + this.getClass()); - } + /** add a value in an array json object. */ + public void addValue(Object current, Object value) throws ParseException, IOException { + throw new RuntimeException( + ERR_MSG + " addValue(Object current, Object value) in " + this.getClass()); + } - /** - * use to instantiate a new object that will be used as an object - */ - public Object createObject() { - throw new RuntimeException(ERR_MSG + " createObject() in " + this.getClass()); - } + /** use to instantiate a new object that will be used as an object */ + public Object createObject() { + throw new RuntimeException(ERR_MSG + " createObject() in " + this.getClass()); + } - /** - * use to instantiate a new object that will be used as an array - */ - public Object createArray() { - throw new RuntimeException(ERR_MSG + " createArray() in " + this.getClass()); - } + /** use to instantiate a new object that will be used as an array */ + public Object createArray() { + throw new RuntimeException(ERR_MSG + " createArray() in " + this.getClass()); + } - /** - * Allow a mapper to convert a temporary structure to the final data format. - * - * example: convert an List<Integer> to an int[] - */ - @SuppressWarnings("unchecked") - public T convert(Object current) { - return (T) current; - } + /** + * Allow a mapper to convert a temporary structure to the final data format. + * + *

example: convert an List<Integer> to an int[] + */ + @SuppressWarnings("unchecked") + public T convert(Object current) { + return (T) current; + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/MapperRemapped.java b/json-smart/src/main/java/net/minidev/json/writer/MapperRemapped.java index 181a3f3..40e712d 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/MapperRemapped.java +++ b/json-smart/src/main/java/net/minidev/json/writer/MapperRemapped.java @@ -4,68 +4,66 @@ import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; - import net.minidev.json.parser.ParseException; /** * Simple solution to support on read field renaming - * - * @author uriel * + * @author uriel * @param */ public class MapperRemapped extends JsonReaderI { - private Map rename; - private JsonReaderI parent; + private Map rename; + private JsonReaderI parent; - public MapperRemapped(JsonReaderI parent) { - super(parent.base); - this.parent = parent; - this.rename = new HashMap(); - } + public MapperRemapped(JsonReaderI parent) { + super(parent.base); + this.parent = parent; + this.rename = new HashMap(); + } - public void renameField(String source, String dest) { - rename.put(source, dest); - } + public void renameField(String source, String dest) { + rename.put(source, dest); + } - private String rename(String key) { - String k2 = rename.get(key); - if (k2 != null) - return k2; - return key; - } + private String rename(String key) { + String k2 = rename.get(key); + if (k2 != null) return k2; + return key; + } - @Override - public void setValue(Object current, String key, Object value) throws ParseException, IOException { - key = rename(key); - parent.setValue(current, key, value); - } + @Override + public void setValue(Object current, String key, Object value) + throws ParseException, IOException { + key = rename(key); + parent.setValue(current, key, value); + } - public Object getValue(Object current, String key) { - key = rename(key); - return parent.getValue(current, key); - } + public Object getValue(Object current, String key) { + key = rename(key); + return parent.getValue(current, key); + } - @Override - public Type getType(String key) { - key = rename(key); - return parent.getType(key); - } + @Override + public Type getType(String key) { + key = rename(key); + return parent.getType(key); + } - @Override - public JsonReaderI startArray(String key) throws ParseException, IOException { - key = rename(key); - return parent.startArray(key); - } + @Override + public JsonReaderI startArray(String key) throws ParseException, IOException { + key = rename(key); + return parent.startArray(key); + } - @Override - public JsonReaderI startObject(String key) throws ParseException, IOException { - key = rename(key); - return parent.startObject(key); - } + @Override + public JsonReaderI startObject(String key) throws ParseException, IOException { + key = rename(key); + return parent.startObject(key); + } - @Override - public Object createObject() { - return parent.createObject(); - } + @Override + public Object createObject() { + return parent.createObject(); + } } diff --git a/json-smart/src/main/java/net/minidev/json/writer/UpdaterMapper.java b/json-smart/src/main/java/net/minidev/json/writer/UpdaterMapper.java index afc52ca..49d7fca 100644 --- a/json-smart/src/main/java/net/minidev/json/writer/UpdaterMapper.java +++ b/json-smart/src/main/java/net/minidev/json/writer/UpdaterMapper.java @@ -2,93 +2,76 @@ import java.io.IOException; import java.lang.reflect.Type; - import net.minidev.json.parser.ParseException; public class UpdaterMapper extends JsonReaderI { - final T obj; - final JsonReaderI mapper; + final T obj; + final JsonReaderI mapper; - public UpdaterMapper(JsonReader base, T obj) { - super(base); - if (obj == null) - throw new NullPointerException("can not update null Object"); - this.obj = obj; - this.mapper = (JsonReaderI) base.getMapper(obj.getClass()); - } + public UpdaterMapper(JsonReader base, T obj) { + super(base); + if (obj == null) throw new NullPointerException("can not update null Object"); + this.obj = obj; + this.mapper = (JsonReaderI) base.getMapper(obj.getClass()); + } - public UpdaterMapper(JsonReader base, T obj, Type type) { - super(base); - if (obj == null) - throw new NullPointerException("can not update null Object"); - this.obj = obj; - this.mapper = (JsonReaderI) base.getMapper(type); - } + public UpdaterMapper(JsonReader base, T obj, Type type) { + super(base); + if (obj == null) throw new NullPointerException("can not update null Object"); + this.obj = obj; + this.mapper = (JsonReaderI) base.getMapper(type); + } - /** - * called when json-smart parser meet an object key - */ - public JsonReaderI startObject(String key) throws ParseException, IOException { - Object bean = mapper.getValue(obj, key); - if (bean == null) - return mapper.startObject(key); - return new UpdaterMapper(base, bean, mapper.getType(key)); - } + /** called when json-smart parser meet an object key */ + public JsonReaderI startObject(String key) throws ParseException, IOException { + Object bean = mapper.getValue(obj, key); + if (bean == null) return mapper.startObject(key); + return new UpdaterMapper(base, bean, mapper.getType(key)); + } - /** - * called when json-smart parser start an array. - * - * @param key - * the destination key name, or null. - */ - public JsonReaderI startArray(String key) throws ParseException, IOException { - // if (obj != null) - return mapper.startArray(key); - } + /** + * called when json-smart parser start an array. + * + * @param key the destination key name, or null. + */ + public JsonReaderI startArray(String key) throws ParseException, IOException { + // if (obj != null) + return mapper.startArray(key); + } - /** - * called when json-smart done parsing a value - */ - public void setValue(Object current, String key, Object value) throws ParseException, IOException { - // if (obj != null) - mapper.setValue(current, key, value); - } + /** called when json-smart done parsing a value */ + public void setValue(Object current, String key, Object value) + throws ParseException, IOException { + // if (obj != null) + mapper.setValue(current, key, value); + } - /** - * add a value in an array json object. - */ - public void addValue(Object current, Object value) throws ParseException, IOException { - // if (obj != null) - mapper.addValue(current, value); - } + /** add a value in an array json object. */ + public void addValue(Object current, Object value) throws ParseException, IOException { + // if (obj != null) + mapper.addValue(current, value); + } - /** - * use to instantiate a new object that will be used as an object - */ - public Object createObject() { - if (obj != null) - return obj; - return mapper.createObject(); - } + /** use to instantiate a new object that will be used as an object */ + public Object createObject() { + if (obj != null) return obj; + return mapper.createObject(); + } - /** - * use to instantiate a new object that will be used as an array - */ - public Object createArray() { - if (obj != null) - return obj; - return mapper.createArray(); - } + /** use to instantiate a new object that will be used as an array */ + public Object createArray() { + if (obj != null) return obj; + return mapper.createArray(); + } - /** - * Allow a mapper to convert a temporary structure to the final data format. - * - * example: convert an List<Integer> to an int[] - */ - @SuppressWarnings("unchecked") - public T convert(Object current) { - if (obj != null) - return obj; - return (T) mapper.convert(current); - } + /** + * Allow a mapper to convert a temporary structure to the final data format. + * + *

example: convert an List<Integer> to an int[] + */ + @SuppressWarnings("unchecked") + public T convert(Object current) { + if (obj != null) return obj; + return (T) mapper.convert(current); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/JSONObjectTest.java b/json-smart/src/test/java/net/minidev/json/test/JSONObjectTest.java index 0507f88..edb0f2b 100644 --- a/json-smart/src/test/java/net/minidev/json/test/JSONObjectTest.java +++ b/json-smart/src/test/java/net/minidev/json/test/JSONObjectTest.java @@ -7,172 +7,186 @@ class JSONObjectTest { - @Test - void mergeIntegerFailed() { - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.appendField("k1", 1); - Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString()); - - // replace with new value by Map merge - jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue); - Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString()); - - JSONObject jsonObject3 = new JSONObject(); - jsonObject3.appendField("k2", 2); - jsonObject1.merge(jsonObject3); - Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString()); - - // replace with new value by JSONObject merge will fail - Exception exception = Assertions.assertThrows(RuntimeException.class, () -> { - JSONObject jsonObject2 = new JSONObject(); - jsonObject2.appendField("k1", 101); - jsonObject1.merge(jsonObject2); - }); - - Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.Integer Object together"); - } - - @Test - void mergeStringFailed() { - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.appendField("k1", "v1"); - Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); - - // replace with new value by Map merge - jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue); - Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString()); - - JSONObject jsonObject3 = new JSONObject(); - jsonObject3.appendField("k2", "v2"); - jsonObject1.merge(jsonObject3); - Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); - - // replace with new value by JSONObject merge will fail - Exception exception = Assertions.assertThrows(RuntimeException.class, () -> { - JSONObject jsonObject2 = new JSONObject(); - jsonObject2.appendField("k1", "vNew2"); - jsonObject1.merge(jsonObject2); - System.out.println(jsonObject1.toJSONString()); - }); - - Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.String Object together"); - } - - @Test - void mergeJsonObjectFailed() { - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.appendField("k1", "v1"); - Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); - - JSONObject jsonObject2 = new JSONObject(); - jsonObject2.appendField("k2", jsonObject1); - Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString()); - - // replace with new value by JSONObject merge will fail - JSONObject jsonObject3 = new JSONObject(); - jsonObject3.appendField("k1", "vNew1"); - - JSONObject jsonObject4 = new JSONObject(); - jsonObject4.appendField("k2", jsonObject3); - Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString()); - - Exception exception = Assertions.assertThrows(RuntimeException.class, () -> { - jsonObject4.merge(jsonObject2); - }); - - Assertions.assertEquals(exception.getMessage(), "JSON merge can not merge two java.lang.String Object together"); - } - - @Test - void mergeJsonArraySuccess() { - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.appendField("k1", "v1"); - JSONObject jsonObject2 = new JSONObject(); - jsonObject2.appendField("k2", "v2"); - - JSONArray jsonArray1 = new JSONArray(); - jsonArray1.add(jsonObject1); - jsonArray1.add(jsonObject2); - Assertions.assertEquals("[{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", jsonArray1.toJSONString()); - - // replace with new value by JSONObject merge will fail - JSONObject jsonObject3 = new JSONObject(); - jsonObject3.appendField("k1", "vNew1"); - JSONObject jsonObject4 = new JSONObject(); - jsonObject4.appendField("k2", "vNew2"); - - JSONArray jsonArray2 = new JSONArray(); - jsonArray2.add(jsonObject3); - jsonArray2.add(jsonObject4); - Assertions.assertEquals("[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"}]", jsonArray2.toJSONString()); - - jsonArray2.merge(jsonArray1); - Assertions.assertEquals("[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"},{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", jsonArray2.toJSONString()); - } - - @Test - void mergeIntegerWithOverwriteSuccess() { - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.appendField("k1", 1); - Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString()); - - // replace with new value by Map merge - jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue); - Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString()); - - JSONObject jsonObject3 = new JSONObject(); - jsonObject3.appendField("k2", 2); - jsonObject1.merge(jsonObject3); - Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString()); - - // replace with new value by JSONObject merge with override success - JSONObject jsonObject2 = new JSONObject(); - jsonObject2.appendField("k1", 101); - jsonObject1.merge(jsonObject2, true); - Assertions.assertEquals("{\"k1\":101,\"k2\":2}", jsonObject1.toJSONString()); - } - - @Test - void mergeStringWithOverwriteSuccess() { - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.appendField("k1", "v1"); - Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); - - // replace with new value by Map merge - jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue); - Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString()); - - JSONObject jsonObject3 = new JSONObject(); - jsonObject3.appendField("k2", "v2"); - jsonObject1.merge(jsonObject3); - Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); - - // replace with new value by JSONObject merge with override success - JSONObject jsonObject2 = new JSONObject(); - jsonObject2.appendField("k1", "vNew2"); - jsonObject1.merge(jsonObject2, true); - Assertions.assertEquals("{\"k1\":\"vNew2\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); - } - - @Test - void mergeJsonObjectWithOverwriteSuccess() { - JSONObject jsonObject1 = new JSONObject(); - jsonObject1.appendField("k1", "v1"); - Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); - - JSONObject jsonObject2 = new JSONObject(); - jsonObject2.appendField("k2", jsonObject1); - Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString()); - - // JSONObject merge will overwrite jsonObject3 by jsonObject2 - JSONObject jsonObject3 = new JSONObject(); - jsonObject3.appendField("k1", "vNew1"); - - JSONObject jsonObject4 = new JSONObject(); - jsonObject4.appendField("k2", jsonObject3); - Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString()); - - jsonObject4.merge(jsonObject2, true); - Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject4.toJSONString()); - } -} \ No newline at end of file + @Test + void mergeIntegerFailed() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", 1); + Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", 2); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge will fail + Exception exception = + Assertions.assertThrows( + RuntimeException.class, + () -> { + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", 101); + jsonObject1.merge(jsonObject2); + }); + + Assertions.assertEquals( + exception.getMessage(), "JSON merge can not merge two java.lang.Integer Object together"); + } + + @Test + void mergeStringFailed() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", "v2"); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge will fail + Exception exception = + Assertions.assertThrows( + RuntimeException.class, + () -> { + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", "vNew2"); + jsonObject1.merge(jsonObject2); + System.out.println(jsonObject1.toJSONString()); + }); + + Assertions.assertEquals( + exception.getMessage(), "JSON merge can not merge two java.lang.String Object together"); + } + + @Test + void mergeJsonObjectFailed() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k2", jsonObject1); + Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString()); + + // replace with new value by JSONObject merge will fail + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k1", "vNew1"); + + JSONObject jsonObject4 = new JSONObject(); + jsonObject4.appendField("k2", jsonObject3); + Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString()); + + Exception exception = + Assertions.assertThrows( + RuntimeException.class, + () -> { + jsonObject4.merge(jsonObject2); + }); + + Assertions.assertEquals( + exception.getMessage(), "JSON merge can not merge two java.lang.String Object together"); + } + + @Test + void mergeJsonArraySuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k2", "v2"); + + JSONArray jsonArray1 = new JSONArray(); + jsonArray1.add(jsonObject1); + jsonArray1.add(jsonObject2); + Assertions.assertEquals("[{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", jsonArray1.toJSONString()); + + // replace with new value by JSONObject merge will fail + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k1", "vNew1"); + JSONObject jsonObject4 = new JSONObject(); + jsonObject4.appendField("k2", "vNew2"); + + JSONArray jsonArray2 = new JSONArray(); + jsonArray2.add(jsonObject3); + jsonArray2.add(jsonObject4); + Assertions.assertEquals("[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"}]", jsonArray2.toJSONString()); + + jsonArray2.merge(jsonArray1); + Assertions.assertEquals( + "[{\"k1\":\"vNew1\"},{\"k2\":\"vNew2\"},{\"k1\":\"v1\"},{\"k2\":\"v2\"}]", + jsonArray2.toJSONString()); + } + + @Test + void mergeIntegerWithOverwriteSuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", 1); + Assertions.assertEquals("{\"k1\":1}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", 11, (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":11}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", 2); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":11,\"k2\":2}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge with override success + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", 101); + jsonObject1.merge(jsonObject2, true); + Assertions.assertEquals("{\"k1\":101,\"k2\":2}", jsonObject1.toJSONString()); + } + + @Test + void mergeStringWithOverwriteSuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + // replace with new value by Map merge + jsonObject1.merge("k1", "vNew1", (oldValue, newValue) -> newValue); + Assertions.assertEquals("{\"k1\":\"vNew1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k2", "v2"); + jsonObject1.merge(jsonObject3); + Assertions.assertEquals("{\"k1\":\"vNew1\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); + + // replace with new value by JSONObject merge with override success + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k1", "vNew2"); + jsonObject1.merge(jsonObject2, true); + Assertions.assertEquals("{\"k1\":\"vNew2\",\"k2\":\"v2\"}", jsonObject1.toJSONString()); + } + + @Test + void mergeJsonObjectWithOverwriteSuccess() { + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.appendField("k1", "v1"); + Assertions.assertEquals("{\"k1\":\"v1\"}", jsonObject1.toJSONString()); + + JSONObject jsonObject2 = new JSONObject(); + jsonObject2.appendField("k2", jsonObject1); + Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject2.toJSONString()); + + // JSONObject merge will overwrite jsonObject3 by jsonObject2 + JSONObject jsonObject3 = new JSONObject(); + jsonObject3.appendField("k1", "vNew1"); + + JSONObject jsonObject4 = new JSONObject(); + jsonObject4.appendField("k2", jsonObject3); + Assertions.assertEquals("{\"k2\":{\"k1\":\"vNew1\"}}", jsonObject4.toJSONString()); + + jsonObject4.merge(jsonObject2, true); + Assertions.assertEquals("{\"k2\":{\"k1\":\"v1\"}}", jsonObject4.toJSONString()); + } +} diff --git a/json-smart/src/test/java/net/minidev/json/test/JSONSimpleTest.java b/json-smart/src/test/java/net/minidev/json/test/JSONSimpleTest.java index 875f426..0a5cee2 100644 --- a/json-smart/src/test/java/net/minidev/json/test/JSONSimpleTest.java +++ b/json-smart/src/test/java/net/minidev/json/test/JSONSimpleTest.java @@ -1,26 +1,25 @@ package net.minidev.json.test; -import net.minidev.json.JSONArray; -import net.minidev.json.parser.JSONParser; - import static org.junit.jupiter.api.Assertions.assertEquals; +import net.minidev.json.JSONArray; +import net.minidev.json.parser.JSONParser; import org.junit.jupiter.api.Test; public class JSONSimpleTest { - @Test - public void testLong() throws Exception { - String s = "[1]"; - JSONParser p = new JSONParser(JSONParser.MODE_JSON_SIMPLE); - JSONArray array = (JSONArray) p.parse(s); - assertEquals(Long.valueOf(1), (Long) array.get(0)); - } + @Test + public void testLong() throws Exception { + String s = "[1]"; + JSONParser p = new JSONParser(JSONParser.MODE_JSON_SIMPLE); + JSONArray array = (JSONArray) p.parse(s); + assertEquals(Long.valueOf(1), (Long) array.get(0)); + } - @Test - public void testDefault() throws Exception { - String s = "[1]"; - JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); - JSONArray array = (JSONArray) p.parse(s); - assertEquals(Integer.valueOf(1), (Integer) array.get(0)); - } + @Test + public void testDefault() throws Exception { + String s = "[1]"; + JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); + JSONArray array = (JSONArray) p.parse(s); + assertEquals(Integer.valueOf(1), (Integer) array.get(0)); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/MustThrows.java b/json-smart/src/test/java/net/minidev/json/test/MustThrows.java index 2c844f4..022b413 100644 --- a/json-smart/src/test/java/net/minidev/json/test/MustThrows.java +++ b/json-smart/src/test/java/net/minidev/json/test/MustThrows.java @@ -1,44 +1,41 @@ package net.minidev.json.test; -import net.minidev.json.parser.JSONParser; -import net.minidev.json.parser.ParseException; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; import org.junit.jupiter.api.Test; public class MustThrows { - @Test - public static void testStrictInvalidJson(String json, int execptionType) throws Exception { - testStrictInvalidJson(json, execptionType, null); - } - - @Test - public static void testStrictInvalidJson(String json, int execptionType, Class cls) throws Exception { - testInvalidJson(json, JSONParser.MODE_RFC4627, execptionType, cls); - } - - @Test - public static void testInvalidJson(String json, int permissifMode, int execptionType) throws Exception { - testInvalidJson(json, permissifMode, execptionType, null); - } - - public static void testInvalidJson(String json, int permissifMode, int execptionType, Class cls) - throws Exception { - JSONParser p = new JSONParser(permissifMode); - try { - if (cls == null) - p.parse(json); - else - p.parse(json, cls); - assertFalse(true, "Exception Should Occure parsing:" + json); - } catch (ParseException e) { - if (execptionType == -1) - execptionType = e.getErrorType(); - assertEquals(execptionType, e.getErrorType()); - } - } - + @Test + public static void testStrictInvalidJson(String json, int execptionType) throws Exception { + testStrictInvalidJson(json, execptionType, null); + } + + @Test + public static void testStrictInvalidJson(String json, int execptionType, Class cls) + throws Exception { + testInvalidJson(json, JSONParser.MODE_RFC4627, execptionType, cls); + } + + @Test + public static void testInvalidJson(String json, int permissifMode, int execptionType) + throws Exception { + testInvalidJson(json, permissifMode, execptionType, null); + } + + public static void testInvalidJson( + String json, int permissifMode, int execptionType, Class cls) throws Exception { + JSONParser p = new JSONParser(permissifMode); + try { + if (cls == null) p.parse(json); + else p.parse(json, cls); + assertFalse(true, "Exception Should Occure parsing:" + json); + } catch (ParseException e) { + if (execptionType == -1) execptionType = e.getErrorType(); + assertEquals(execptionType, e.getErrorType()); + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/SerializeReadonlyField.java b/json-smart/src/test/java/net/minidev/json/test/SerializeReadonlyField.java index cb6cd00..a3287fc 100644 --- a/json-smart/src/test/java/net/minidev/json/test/SerializeReadonlyField.java +++ b/json-smart/src/test/java/net/minidev/json/test/SerializeReadonlyField.java @@ -1,8 +1,5 @@ package net.minidev.json.test; -import net.minidev.json.JSONObject; -import net.minidev.json.JSONValue; - import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.file.Path; @@ -10,48 +7,45 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; - +import net.minidev.json.JSONObject; +import net.minidev.json.JSONValue; import org.junit.jupiter.api.Test; public class SerializeReadonlyField { - /** - * https://github.com/netplex/json-smart-v2/issues/49 - */ - @Test - public static void main(String[] args) { - MyData data = new MyData("a"); - Map m = new HashMap<>(); - m.put("data", data); - String a = new JSONObject(m).toString(); - assertEquals("{\"data\":{\"someField\":\"a\"}}", a.toString()); - } - - public static class MyData { - private String someField; - - public MyData(String someField) { - this.someField = someField; - } - - public String getSomeField() { - return someField; - } - - // Remove comment to make serialization to work - /* - * public void setSomeField(String someField) { this.someField = someField; } - */ - } - - /** - * https://github.com/netplex/json-smart-v2/issues/59 - */ - @Test - public void test() { - // should not crash - Map cachedTable1 = new LinkedHashMap<>(); - Iterable path = Paths.get("/"); - cachedTable1.put("1", path); - JSONValue.toJSONString(cachedTable1); + /** https://github.com/netplex/json-smart-v2/issues/49 */ + @Test + public static void main(String[] args) { + MyData data = new MyData("a"); + Map m = new HashMap<>(); + m.put("data", data); + String a = new JSONObject(m).toString(); + assertEquals("{\"data\":{\"someField\":\"a\"}}", a.toString()); + } + + public static class MyData { + private String someField; + + public MyData(String someField) { + this.someField = someField; + } + + public String getSomeField() { + return someField; } + + // Remove comment to make serialization to work + /* + * public void setSomeField(String someField) { this.someField = someField; } + */ + } + + /** https://github.com/netplex/json-smart-v2/issues/59 */ + @Test + public void test() { + // should not crash + Map cachedTable1 = new LinkedHashMap<>(); + Iterable path = Paths.get("/"); + cachedTable1.put("1", path); + JSONValue.toJSONString(cachedTable1); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestBigDigitUnrestricted.java b/json-smart/src/test/java/net/minidev/json/test/TestBigDigitUnrestricted.java index 5d6933b..35f01b8 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestBigDigitUnrestricted.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestBigDigitUnrestricted.java @@ -3,31 +3,35 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.math.BigDecimal; - import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; - import org.junit.jupiter.api.Test; public class TestBigDigitUnrestricted { - public static String[] VALID_DOUBLE_JSON = new String[] {"{\"v\":0.12345678912345678}", "\"v\":\"1.7976931348623157E308\"", "\"v\":\"1.7976931348623157E+308\"", "\"v\":\"1.7976931348623157e+308\""}; - - @Test - public void testRestrictedBigDigit() throws Exception { - JSONParser p = new JSONParser(JSONParser.MODE_RFC4627); - String json = VALID_DOUBLE_JSON[0]; - JSONObject obj = (JSONObject) p.parse(json); - Object value = obj.get("v"); - assertEquals(Double.class, value.getClass(), "Should not Store this big number as a double"); - } - - @Test - public void testUnrestrictedBigDigit() throws Exception { - JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); - String json = VALID_DOUBLE_JSON[0]; - JSONObject obj = (JSONObject) p.parse(json); - Object value = obj.get("v"); - assertEquals(BigDecimal.class, value.getClass(), "Should not Store this big number as a double"); - } + public static String[] VALID_DOUBLE_JSON = + new String[] { + "{\"v\":0.12345678912345678}", + "\"v\":\"1.7976931348623157E308\"", + "\"v\":\"1.7976931348623157E+308\"", + "\"v\":\"1.7976931348623157e+308\"" + }; + + @Test + public void testRestrictedBigDigit() throws Exception { + JSONParser p = new JSONParser(JSONParser.MODE_RFC4627); + String json = VALID_DOUBLE_JSON[0]; + JSONObject obj = (JSONObject) p.parse(json); + Object value = obj.get("v"); + assertEquals(Double.class, value.getClass(), "Should not Store this big number as a double"); + } + @Test + public void testUnrestrictedBigDigit() throws Exception { + JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); + String json = VALID_DOUBLE_JSON[0]; + JSONObject obj = (JSONObject) p.parse(json); + Object value = obj.get("v"); + assertEquals( + BigDecimal.class, value.getClass(), "Should not Store this big number as a double"); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestBigValue.java b/json-smart/src/test/java/net/minidev/json/test/TestBigValue.java index 1184fc9..a9e74b8 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestBigValue.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestBigValue.java @@ -5,44 +5,38 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.HashMap; - import net.minidev.json.JSONObject; import net.minidev.json.JSONValue; - import org.junit.jupiter.api.Test; public class TestBigValue { - String bigStr = "12345678901234567890123456789"; + String bigStr = "12345678901234567890123456789"; - /** - * test BigDecimal serialization - */ - @Test - public void testBigDecimal() { - HashMap map = new HashMap(); - BigDecimal bigDec = new BigDecimal(bigStr + "." + bigStr); - map.put("big", bigDec); - String test = JSONValue.toJSONString(map); - String result = "{\"big\":" + bigStr + "." +bigStr + "}"; - assertEquals(result, test); - JSONObject obj = (JSONObject)JSONValue.parse(test); - assertEquals(bigDec, obj.get("big")); - assertEquals(bigDec.getClass(), obj.get("big").getClass()); - } + /** test BigDecimal serialization */ + @Test + public void testBigDecimal() { + HashMap map = new HashMap(); + BigDecimal bigDec = new BigDecimal(bigStr + "." + bigStr); + map.put("big", bigDec); + String test = JSONValue.toJSONString(map); + String result = "{\"big\":" + bigStr + "." + bigStr + "}"; + assertEquals(result, test); + JSONObject obj = (JSONObject) JSONValue.parse(test); + assertEquals(bigDec, obj.get("big")); + assertEquals(bigDec.getClass(), obj.get("big").getClass()); + } - /** - * test BigInteger serialization - */ - @Test - public void testBigInteger() { - HashMap map = new HashMap(); - BigInteger bigInt = new BigInteger(bigStr); - map.put("big", bigInt); - String test = JSONValue.toJSONString(map); - String result = "{\"big\":" + bigStr + "}"; - assertEquals(result, test); - JSONObject obj = (JSONObject)JSONValue.parse(test); - assertEquals(bigInt, obj.get("big")); - assertEquals(bigInt.getClass(), obj.get("big").getClass()); - } + /** test BigInteger serialization */ + @Test + public void testBigInteger() { + HashMap map = new HashMap(); + BigInteger bigInt = new BigInteger(bigStr); + map.put("big", bigInt); + String test = JSONValue.toJSONString(map); + String result = "{\"big\":" + bigStr + "}"; + assertEquals(result, test); + JSONObject obj = (JSONObject) JSONValue.parse(test); + assertEquals(bigInt, obj.get("big")); + assertEquals(bigInt.getClass(), obj.get("big").getClass()); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestCVE202457699.java b/json-smart/src/test/java/net/minidev/json/test/TestCVE202457699.java index afd0d9e..365e77b 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestCVE202457699.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestCVE202457699.java @@ -1,56 +1,60 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertThrows; + import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class TestCVE202457699 { - private static final String MALICIOUS_STRING = createMaliciousString(); - - @Test - public void jsonSimpleParserShouldRestrictDepth() { - JSONParser p = new JSONParser(JSONParser.MODE_JSON_SIMPLE); - assertThrows(ParseException.class, - () -> p.parse(MALICIOUS_STRING), - "Malicious payload, having non natural depths"); - } - - @Test - public void strictestParserShouldRestrictDepth() { - JSONParser p = new JSONParser(JSONParser.MODE_STRICTEST); - assertThrows(ParseException.class, - () -> p.parse(MALICIOUS_STRING), - "Malicious payload, having non natural depths"); - } - - @Test - public void rfc4627ParserShouldRestrictDepth() { - JSONParser p = new JSONParser(JSONParser.MODE_RFC4627); - assertThrows(ParseException.class, - () -> p.parse(MALICIOUS_STRING), - "Malicious payload, having non natural depths"); + private static final String MALICIOUS_STRING = createMaliciousString(); + + @Test + public void jsonSimpleParserShouldRestrictDepth() { + JSONParser p = new JSONParser(JSONParser.MODE_JSON_SIMPLE); + assertThrows( + ParseException.class, + () -> p.parse(MALICIOUS_STRING), + "Malicious payload, having non natural depths"); + } + + @Test + public void strictestParserShouldRestrictDepth() { + JSONParser p = new JSONParser(JSONParser.MODE_STRICTEST); + assertThrows( + ParseException.class, + () -> p.parse(MALICIOUS_STRING), + "Malicious payload, having non natural depths"); + } + + @Test + public void rfc4627ParserShouldRestrictDepth() { + JSONParser p = new JSONParser(JSONParser.MODE_RFC4627); + assertThrows( + ParseException.class, + () -> p.parse(MALICIOUS_STRING), + "Malicious payload, having non natural depths"); + } + + @Test + public void permissiveParserShouldRestrictDepth() { + JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); + assertThrows( + ParseException.class, + () -> p.parse(MALICIOUS_STRING), + "Malicious payload, having non natural depths"); + } + + private static String createMaliciousString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 10000; i++) { + sb.append("{\"a\":"); } - - @Test - public void permissiveParserShouldRestrictDepth() { - JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); - assertThrows(ParseException.class, - () -> p.parse(MALICIOUS_STRING), - "Malicious payload, having non natural depths"); - } - - private static String createMaliciousString() { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 10000 ; i++) { - sb.append("{\"a\":"); - } - sb.append("1"); - for (int i = 0; i < 10000 ; i++) { - sb.append("}"); - } - return sb.toString(); + sb.append("1"); + for (int i = 0; i < 10000; i++) { + sb.append("}"); } + return sb.toString(); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestCompressor.java b/json-smart/src/test/java/net/minidev/json/test/TestCompressor.java index 5c0b9b4..7ea9245 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestCompressor.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestCompressor.java @@ -1,58 +1,56 @@ package net.minidev.json.test; -import net.minidev.json.JSONValue; - import static org.junit.jupiter.api.Assertions.assertEquals; +import net.minidev.json.JSONValue; import org.junit.jupiter.api.Test; public class TestCompressor { - @Test - public void testCompressor() { - String j = "{'a':{'b':'c','d':'e'},f:[1,2,'XYZ']}".replace('\'', '"'); - String sol = j.replace(" ", "").replace("\"", ""); - String comp = JSONValue.compress(j); - assertEquals(sol, comp); - } - - @Test - public void testCompressor2() { - String j = "[{} ]"; - String sol = j.replace(" ", ""); - String comp = JSONValue.compress(j); - assertEquals(sol, comp); - } - - @Test - public void testCompressor3() { - String j = "[[],[],[] ]"; - String sol = j.replace(" ", ""); - String comp = JSONValue.compress(j); - assertEquals(sol, comp); - } - - @Test - public void testCompressor4() { - String j = "[[1],[2,3],[4] ]"; - String sol = j.replace(" ", ""); - String comp = JSONValue.compress(j); - assertEquals(sol, comp); - } - - @Test - public void testCompressor5() { - String j = "[{},{},{} ]"; - String sol = j.replace(" ", ""); - String comp = JSONValue.compress(j); - assertEquals(sol, comp); - } - - @Test - public void testCompressor6() { - String j = "[{a:b},{c:d},{e:f}]"; - String sol = j; - String comp = JSONValue.compress(j); - assertEquals(sol, comp); - } - + @Test + public void testCompressor() { + String j = "{'a':{'b':'c','d':'e'},f:[1,2,'XYZ']}".replace('\'', '"'); + String sol = j.replace(" ", "").replace("\"", ""); + String comp = JSONValue.compress(j); + assertEquals(sol, comp); + } + + @Test + public void testCompressor2() { + String j = "[{} ]"; + String sol = j.replace(" ", ""); + String comp = JSONValue.compress(j); + assertEquals(sol, comp); + } + + @Test + public void testCompressor3() { + String j = "[[],[],[] ]"; + String sol = j.replace(" ", ""); + String comp = JSONValue.compress(j); + assertEquals(sol, comp); + } + + @Test + public void testCompressor4() { + String j = "[[1],[2,3],[4] ]"; + String sol = j.replace(" ", ""); + String comp = JSONValue.compress(j); + assertEquals(sol, comp); + } + + @Test + public void testCompressor5() { + String j = "[{},{},{} ]"; + String sol = j.replace(" ", ""); + String comp = JSONValue.compress(j); + assertEquals(sol, comp); + } + + @Test + public void testCompressor6() { + String j = "[{a:b},{c:d},{e:f}]"; + String sol = j; + String comp = JSONValue.compress(j); + assertEquals(sol, comp); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestCompressorFlags.java b/json-smart/src/test/java/net/minidev/json/test/TestCompressorFlags.java index aaeb79c..81eec30 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestCompressorFlags.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestCompressorFlags.java @@ -1,100 +1,93 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; + import net.minidev.json.JSONObject; import net.minidev.json.JSONStyle; import net.minidev.json.JSONValue; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; /** * Test all Compression Styles - * - * @author Uriel Chemouni <uchemouni@gmail.com> * + * @author Uriel Chemouni <uchemouni@gmail.com> */ public class TestCompressorFlags { - @Test - public void testProtect() throws Exception { - String compressed = "{k:value}"; - String nCompress = "{\"k\":\"value\"}"; - - JSONObject obj = (JSONObject) JSONValue.parse(nCompress); - - // test MAX_COMPRESS - String r = obj.toJSONString(JSONStyle.MAX_COMPRESS); - assertEquals(compressed, r); - - // test LT_COMPRESS - r = obj.toJSONString(JSONStyle.LT_COMPRESS); - assertEquals(nCompress, r); - - // test NO_COMPRESS - r = obj.toJSONString(JSONStyle.NO_COMPRESS); - assertEquals(nCompress, r); - - // only keys values - JSONStyle style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_KEYS); - r = obj.toJSONString(style); - assertEquals("{k:\"value\"}", r); - - // only protect values - style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_VALUES); - r = obj.toJSONString(style); - assertEquals("{\"k\":value}", r); - } - - @Test - public void testAggresive() throws Exception { - String r; - JSONStyle style; - - String NProtectValue = "{\"a b\":\"c d\"}"; - JSONObject obj = (JSONObject) JSONValue.parse(NProtectValue); - - /** - * Test Without Agressive - */ - style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_KEYS); - r = obj.toJSONString(style); - assertEquals(NProtectValue, r); - - style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_VALUES); - r = obj.toJSONString(style); - assertEquals(NProtectValue, r); - - /** - * Test With Agressive - */ - style = new JSONStyle(-1 & (JSONStyle.FLAG_PROTECT_VALUES | JSONStyle.FLAG_AGRESSIVE)); - r = obj.toJSONString(style); - assertEquals("{\"a b\":c d}", r); - - style = new JSONStyle(-1 & (JSONStyle.FLAG_PROTECT_KEYS | JSONStyle.FLAG_AGRESSIVE)); - r = obj.toJSONString(style); - assertEquals("{a b:\"c d\"}", r); - - style = JSONStyle.MAX_COMPRESS; - r = obj.toJSONString(style); - assertEquals("{a b:c d}", r); - } - - @Test - public void test4Web() throws Exception { - String NProtectValue = "{\"k\":\"http:\\/\\/url\"}"; - - JSONObject obj = (JSONObject) JSONValue.parse(NProtectValue); - - String r = obj.toJSONString(JSONStyle.MAX_COMPRESS); - assertEquals("{k:\"http://url\"}", r); - - r = obj.toJSONString(JSONStyle.LT_COMPRESS); - assertEquals("{\"k\":\"http://url\"}", r); - - r = obj.toJSONString(JSONStyle.NO_COMPRESS); - assertEquals("{\"k\":\"http:\\/\\/url\"}", r); - } + @Test + public void testProtect() throws Exception { + String compressed = "{k:value}"; + String nCompress = "{\"k\":\"value\"}"; + + JSONObject obj = (JSONObject) JSONValue.parse(nCompress); + + // test MAX_COMPRESS + String r = obj.toJSONString(JSONStyle.MAX_COMPRESS); + assertEquals(compressed, r); + + // test LT_COMPRESS + r = obj.toJSONString(JSONStyle.LT_COMPRESS); + assertEquals(nCompress, r); + + // test NO_COMPRESS + r = obj.toJSONString(JSONStyle.NO_COMPRESS); + assertEquals(nCompress, r); + + // only keys values + JSONStyle style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_KEYS); + r = obj.toJSONString(style); + assertEquals("{k:\"value\"}", r); + + // only protect values + style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_VALUES); + r = obj.toJSONString(style); + assertEquals("{\"k\":value}", r); + } + + @Test + public void testAggresive() throws Exception { + String r; + JSONStyle style; + + String NProtectValue = "{\"a b\":\"c d\"}"; + JSONObject obj = (JSONObject) JSONValue.parse(NProtectValue); + + /** Test Without Agressive */ + style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_KEYS); + r = obj.toJSONString(style); + assertEquals(NProtectValue, r); + + style = new JSONStyle(-1 & JSONStyle.FLAG_PROTECT_VALUES); + r = obj.toJSONString(style); + assertEquals(NProtectValue, r); + + /** Test With Agressive */ + style = new JSONStyle(-1 & (JSONStyle.FLAG_PROTECT_VALUES | JSONStyle.FLAG_AGRESSIVE)); + r = obj.toJSONString(style); + assertEquals("{\"a b\":c d}", r); + + style = new JSONStyle(-1 & (JSONStyle.FLAG_PROTECT_KEYS | JSONStyle.FLAG_AGRESSIVE)); + r = obj.toJSONString(style); + assertEquals("{a b:\"c d\"}", r); + + style = JSONStyle.MAX_COMPRESS; + r = obj.toJSONString(style); + assertEquals("{a b:c d}", r); + } + + @Test + public void test4Web() throws Exception { + String NProtectValue = "{\"k\":\"http:\\/\\/url\"}"; + + JSONObject obj = (JSONObject) JSONValue.parse(NProtectValue); + + String r = obj.toJSONString(JSONStyle.MAX_COMPRESS); + assertEquals("{k:\"http://url\"}", r); + + r = obj.toJSONString(JSONStyle.LT_COMPRESS); + assertEquals("{\"k\":\"http://url\"}", r); + r = obj.toJSONString(JSONStyle.NO_COMPRESS); + assertEquals("{\"k\":\"http:\\/\\/url\"}", r); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestFloat.java b/json-smart/src/test/java/net/minidev/json/test/TestFloat.java index 8c2553e..d50c3c6 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestFloat.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestFloat.java @@ -1,69 +1,83 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import net.minidev.json.JSONObject; import net.minidev.json.JSONStyle; import net.minidev.json.parser.JSONParser; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; public class TestFloat { - public static String[] TRUE_NUMBERS = new String[] { "1.0", "123.456", "1.0E1", "123.456E12", "1.0E+1", - "123.456E+12", "1.0E-1", "123.456E-12", "1.0e1", "123.456e12", "1.0e+1", "123.456e+12", "1.0e-1", - "123.456e-12" }; + public static String[] TRUE_NUMBERS = + new String[] { + "1.0", + "123.456", + "1.0E1", + "123.456E12", + "1.0E+1", + "123.456E+12", + "1.0E-1", + "123.456E-12", + "1.0e1", + "123.456e12", + "1.0e+1", + "123.456e+12", + "1.0e-1", + "123.456e-12" + }; + + public static String[] FALSE_NUMBERS = + new String[] {"1.0%", "123.45.6", "1.0E", "++123.456E12", "+-01", "1.0E+1.2"}; + + @Test + public void testPrecisionFloat() throws Exception { + JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); + for (int len = 15; len < 25; len++) { + StringBuilder sb = new StringBuilder("0."); + for (int i = 0; i < len; i++) { + sb.append("123456789".charAt(i % 9)); + } + String s = sb.toString(); + String json = "{v:" + s + "}"; + JSONObject obj = (JSONObject) p.parse(json); + Object value = obj.get("v").toString(); + assertEquals(s, value, "Should not loose precision on a " + len + " digits long"); + } + } + + @Test + public void testFloat() throws Exception { + JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); + for (String s : TRUE_NUMBERS) { + String json = "{v:" + s + "}"; + Double val = Double.valueOf(s.trim()); + JSONObject obj = (JSONObject) p.parse(json); + Object value = obj.get("v"); + assertEquals(val, value, "Should be parse as double"); + } + } - public static String[] FALSE_NUMBERS = new String[] { "1.0%", "123.45.6", "1.0E", "++123.456E12", "+-01", - "1.0E+1.2" }; - - @Test - public void testPrecisionFloat() throws Exception { - JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); - for (int len = 15; len < 25; len++) { - StringBuilder sb = new StringBuilder("0."); - for (int i = 0; i < len; i++) { - sb.append("123456789".charAt(i % 9)); - } - String s = sb.toString(); - String json = "{v:" + s + "}"; - JSONObject obj = (JSONObject) p.parse(json); - Object value = obj.get("v").toString(); - assertEquals(s, value, "Should not loose precision on a " + len + " digits long"); - } - } - - @Test - public void testFloat() throws Exception { - JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); - for (String s : TRUE_NUMBERS) { - String json = "{v:" + s + "}"; - Double val = Double.valueOf(s.trim()); - JSONObject obj = (JSONObject) p.parse(json); - Object value = obj.get("v"); - assertEquals(val, value, "Should be parse as double"); - } - } + @Test + public void testNonFloat() throws Exception { + JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); + for (String s : FALSE_NUMBERS) { + String json = "{v:" + s + "}"; + JSONObject obj = (JSONObject) p.parse(json); + assertEquals(s, obj.get("v"), "Should be parse as string"); - @Test - public void testNonFloat() throws Exception { - JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE); - for (String s : FALSE_NUMBERS) { - String json = "{v:" + s + "}"; - JSONObject obj = (JSONObject) p.parse(json); - assertEquals(s, obj.get("v"), "Should be parse as string"); + String correct = "{\"v\":\"" + s + "\"}"; + assertEquals(correct, obj.toJSONString(), "Should be re serialized as"); + } + } - String correct = "{\"v\":\"" + s + "\"}"; - assertEquals(correct, obj.toJSONString(), "Should be re serialized as"); - } - } - /** - * Error reported in issue 44 - */ - @Test - public void testUUID() { - String UUID = "58860611416142319131902418361e88"; - JSONObject obj = new JSONObject(); - obj.put("uuid", UUID); - String compressed = obj.toJSONString(JSONStyle.MAX_COMPRESS); - assertTrue(compressed.contains("uuid:\"")); - } + /** Error reported in issue 44 */ + @Test + public void testUUID() { + String UUID = "58860611416142319131902418361e88"; + JSONObject obj = new JSONObject(); + obj.put("uuid", UUID); + String compressed = obj.toJSONString(JSONStyle.MAX_COMPRESS); + assertTrue(compressed.contains("uuid:\"")); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestFloatStrict.java b/json-smart/src/test/java/net/minidev/json/test/TestFloatStrict.java index 43a9691..7b6d923 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestFloatStrict.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestFloatStrict.java @@ -2,29 +2,28 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; +import org.junit.jupiter.api.Test; public class TestFloatStrict { - @Test - public void testFloat() throws Exception { - for (String s : TestFloat.TRUE_NUMBERS) { - String json = "{\"v\":" + s + "}"; - Double val = Double.valueOf(s.trim()); - JSONObject obj = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(json); - Object value = obj.get("v"); - assertEquals(val, value, "Should be parse as double"); - } - } + @Test + public void testFloat() throws Exception { + for (String s : TestFloat.TRUE_NUMBERS) { + String json = "{\"v\":" + s + "}"; + Double val = Double.valueOf(s.trim()); + JSONObject obj = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(json); + Object value = obj.get("v"); + assertEquals(val, value, "Should be parse as double"); + } + } - @Test - public void testNonFloat() throws Exception { - for (String s : TestFloat.FALSE_NUMBERS) { - String json = "{\"v\":" + s + "}"; - MustThrows.testStrictInvalidJson(json, -1); - } - } + @Test + public void testNonFloat() throws Exception { + for (String s : TestFloat.FALSE_NUMBERS) { + String json = "{\"v\":" + s + "}"; + MustThrows.testStrictInvalidJson(json, -1); + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestGitHubIssue.java b/json-smart/src/test/java/net/minidev/json/test/TestGitHubIssue.java index 1c30e94..6684aa0 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestGitHubIssue.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestGitHubIssue.java @@ -1,20 +1,21 @@ package net.minidev.json.test; -import org.junit.jupiter.api.Test; +import static net.minidev.json.parser.JSONParser.MODE_PERMISSIVE; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; - -import static net.minidev.json.parser.JSONParser.MODE_PERMISSIVE; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestGitHubIssue { - @Test - public void issue68() { - Assertions.assertThrows(ParseException.class, () -> { - JSONParser parser = new JSONParser(MODE_PERMISSIVE); - String input = "'1"; - parser.parse(input); - }); - } + @Test + public void issue68() { + Assertions.assertThrows( + ParseException.class, + () -> { + JSONParser parser = new JSONParser(MODE_PERMISSIVE); + String input = "'1"; + parser.parse(input); + }); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestInts.java b/json-smart/src/test/java/net/minidev/json/test/TestInts.java index a1a061f..528c9b8 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestInts.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestInts.java @@ -4,98 +4,93 @@ import java.math.BigDecimal; import java.math.BigInteger; - -import org.junit.jupiter.api.Test; - import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; +import org.junit.jupiter.api.Test; public class TestInts { - @Test - public void testIntMax() throws Exception { - String s = "{t:" + Integer.MAX_VALUE + "}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), Integer.MAX_VALUE); - } - - @Test - public void testIntMin() throws Exception { - String s = "{t:" + Integer.MIN_VALUE + "}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), Integer.MIN_VALUE); - } - - @Test - public void testIntResult() throws Exception { - String s = "{\"t\":1}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - assertEquals(o.get("t"), Integer.valueOf(1)); - - o = (JSONObject) new JSONParser(JSONParser.MODE_JSON_SIMPLE).parse(s); - assertEquals(o.get("t"), Long.valueOf(1)); - - o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), Integer.valueOf(1)); - } - - @Test - public void testInt() throws Exception { - String s = "{t:90}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), Integer.valueOf(90)); - } - - @Test - public void testIntNeg() throws Exception { - String s = "{t:-90}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), -90); - } - - @Test - public void testBigInt() throws Exception { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 10; i++) - sb.append(Integer.MAX_VALUE); - String bigText = sb.toString(); - BigInteger big = new BigInteger(bigText, 10); - String s = "{t:" + bigText + "}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), big); - } - - @Test - public void testBigDoubleInt() throws Exception { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 10; i++) - sb.append(Integer.MAX_VALUE); - sb.append('.'); - for (int i = 0; i < 10; i++) - sb.append(Integer.MAX_VALUE); - - String bigText = sb.toString(); - BigDecimal big = new BigDecimal(bigText); - String s = "{\"t\":" + bigText + "}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - assertEquals(o.get("t"), big); - o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), big); - } - - @Test - public void testjunkTaillingData() throws Exception { - String s = "{\"t\":124}$ifsisg045"; - - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_JSON_SIMPLE).parse(s); - assertEquals(o.get("t"), 124L); - - MustThrows.testInvalidJson(s, JSONParser.MODE_RFC4627, ParseException.ERROR_UNEXPECTED_TOKEN); - // o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - // assertEquals(o.get("t"), 124); - - o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), 124); - } + @Test + public void testIntMax() throws Exception { + String s = "{t:" + Integer.MAX_VALUE + "}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), Integer.MAX_VALUE); + } + + @Test + public void testIntMin() throws Exception { + String s = "{t:" + Integer.MIN_VALUE + "}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), Integer.MIN_VALUE); + } + + @Test + public void testIntResult() throws Exception { + String s = "{\"t\":1}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + assertEquals(o.get("t"), Integer.valueOf(1)); + + o = (JSONObject) new JSONParser(JSONParser.MODE_JSON_SIMPLE).parse(s); + assertEquals(o.get("t"), Long.valueOf(1)); + + o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), Integer.valueOf(1)); + } + + @Test + public void testInt() throws Exception { + String s = "{t:90}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), Integer.valueOf(90)); + } + + @Test + public void testIntNeg() throws Exception { + String s = "{t:-90}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), -90); + } + + @Test + public void testBigInt() throws Exception { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 10; i++) sb.append(Integer.MAX_VALUE); + String bigText = sb.toString(); + BigInteger big = new BigInteger(bigText, 10); + String s = "{t:" + bigText + "}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), big); + } + + @Test + public void testBigDoubleInt() throws Exception { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 10; i++) sb.append(Integer.MAX_VALUE); + sb.append('.'); + for (int i = 0; i < 10; i++) sb.append(Integer.MAX_VALUE); + + String bigText = sb.toString(); + BigDecimal big = new BigDecimal(bigText); + String s = "{\"t\":" + bigText + "}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + assertEquals(o.get("t"), big); + o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), big); + } + + @Test + public void testjunkTaillingData() throws Exception { + String s = "{\"t\":124}$ifsisg045"; + + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_JSON_SIMPLE).parse(s); + assertEquals(o.get("t"), 124L); + + MustThrows.testInvalidJson(s, JSONParser.MODE_RFC4627, ParseException.ERROR_UNEXPECTED_TOKEN); + // o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + // assertEquals(o.get("t"), 124); + + o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), 124); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestInvalidNumber.java b/json-smart/src/test/java/net/minidev/json/test/TestInvalidNumber.java index 1c90daa..d25a8b6 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestInvalidNumber.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestInvalidNumber.java @@ -3,79 +3,79 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import org.junit.jupiter.api.Test; - import net.minidev.json.JSONObject; import net.minidev.json.JSONStyle; import net.minidev.json.JSONValue; +import org.junit.jupiter.api.Test; + /** * test invalid number that will be handle ad string - * @author uriel * + * @author uriel */ public class TestInvalidNumber { - private void validFloatAsFloat(String test) { - JSONObject o = new JSONObject(); - o.put("a", test); - String comp = JSONValue.toJSONString(o, JSONStyle.MAX_COMPRESS); - assertEquals("{a:\"" + test + "\"}", comp); - o = JSONValue.parse(comp, JSONObject.class); - Object convertedValue = o.get("a"); - assertEquals(convertedValue, test, "Should handle valid number '" + test + "' as number"); - } - - private void invalidFloatAsText(String test) { - JSONObject o = new JSONObject(); - o.put("a", test); - String comp = JSONValue.toJSONString(o, JSONStyle.MAX_COMPRESS); - assertEquals("{a:" + test + "}", comp); - o = JSONValue.parse(comp, JSONObject.class); - Object convertedValue = o.get("a"); - assertEquals(convertedValue, test, "should handle invalid number '" + test + "' as string"); - } - - @Test - public void testF1() { - validFloatAsFloat("51e88"); - } + private void validFloatAsFloat(String test) { + JSONObject o = new JSONObject(); + o.put("a", test); + String comp = JSONValue.toJSONString(o, JSONStyle.MAX_COMPRESS); + assertEquals("{a:\"" + test + "\"}", comp); + o = JSONValue.parse(comp, JSONObject.class); + Object convertedValue = o.get("a"); + assertEquals(convertedValue, test, "Should handle valid number '" + test + "' as number"); + } + + private void invalidFloatAsText(String test) { + JSONObject o = new JSONObject(); + o.put("a", test); + String comp = JSONValue.toJSONString(o, JSONStyle.MAX_COMPRESS); + assertEquals("{a:" + test + "}", comp); + o = JSONValue.parse(comp, JSONObject.class); + Object convertedValue = o.get("a"); + assertEquals(convertedValue, test, "should handle invalid number '" + test + "' as string"); + } + + @Test + public void testF1() { + validFloatAsFloat("51e88"); + } - @Test - public void testF2() { - validFloatAsFloat("51e+88"); - } + @Test + public void testF2() { + validFloatAsFloat("51e+88"); + } - @Test - public void testF3() { - validFloatAsFloat("51e-88"); - } + @Test + public void testF3() { + validFloatAsFloat("51e-88"); + } - @Test - public void testF4() { - invalidFloatAsText("51ee88"); - } + @Test + public void testF4() { + invalidFloatAsText("51ee88"); + } - @Test - public void testCVE_2021_27568() { - try { - JSONValue.parseWithException("{a:-.}"); - assertFalse(true, "should Throws Exception before"); - } catch (Exception e) { - assertEquals(e.getMessage(), "Unexpected token -. at position 5.", "should throw EOF"); - } + @Test + public void testCVE_2021_27568() { + try { + JSONValue.parseWithException("{a:-.}"); + assertFalse(true, "should Throws Exception before"); + } catch (Exception e) { + assertEquals(e.getMessage(), "Unexpected token -. at position 5.", "should throw EOF"); + } - try { - JSONValue.parseWithException("{a:2e+}"); - assertFalse(true, "should Throws Exception before"); - } catch (Exception e) { - assertEquals(e.getMessage(), "Unexpected token 2e+ at position 6.", "should throw EOF"); - } + try { + JSONValue.parseWithException("{a:2e+}"); + assertFalse(true, "should Throws Exception before"); + } catch (Exception e) { + assertEquals(e.getMessage(), "Unexpected token 2e+ at position 6.", "should throw EOF"); + } - try { - JSONValue.parseWithException("{a:[45e-}"); - assertFalse(true, "should Throws Exception before"); - } catch (Exception e) { - assertEquals(e.getMessage(), "Unexpected End Of File position 8: EOF", "should throw EOF"); - } - } + try { + JSONValue.parseWithException("{a:[45e-}"); + assertFalse(true, "should Throws Exception before"); + } catch (Exception e) { + assertEquals(e.getMessage(), "Unexpected End Of File position 8: EOF", "should throw EOF"); + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestKeyword.java b/json-smart/src/test/java/net/minidev/json/test/TestKeyword.java index f55265e..163e521 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestKeyword.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestKeyword.java @@ -1,44 +1,43 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; - import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; public class TestKeyword { - @Test - public void testBool() throws Exception { - String s = "{t:true}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), true); - - s = "{t:false}"; - o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), false); - } - - @Test - public void testNull() throws Exception { - String s = "{t:null}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertNull(o.get("t")); - } - - @Test - public void testNaN() throws Exception { - String s = "{t:NaN}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), Float.NaN); - } - - @Test - public void testNaNStrict() throws Exception { - String s = "{\"t\":NaN}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_TOKEN); - } - + @Test + public void testBool() throws Exception { + String s = "{t:true}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), true); + + s = "{t:false}"; + o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), false); + } + + @Test + public void testNull() throws Exception { + String s = "{t:null}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertNull(o.get("t")); + } + + @Test + public void testNaN() throws Exception { + String s = "{t:NaN}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), Float.NaN); + } + + @Test + public void testNaNStrict() throws Exception { + String s = "{\"t\":NaN}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_TOKEN); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestMisc.java b/json-smart/src/test/java/net/minidev/json/test/TestMisc.java index 9fe0a00..d907bec 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestMisc.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestMisc.java @@ -1,74 +1,72 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; + import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.JSONValue; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; public class TestMisc { - @Test - public void testIssue23() throws Exception { - String s = JSONValue.toJSONString(new int[] { 1, 2, 50, 1234, 10000 }); - assertEquals("[1,2,50,1234,10000]", s); - } - - @Test - public void testEmptyStrict() throws Exception { - String s = "{\"key1\":\"v1\", \"key2\":{}, \"key3\":[]}"; - JSONObject o = (JSONObject) JSONValue.parseStrict(s); + @Test + public void testIssue23() throws Exception { + String s = JSONValue.toJSONString(new int[] {1, 2, 50, 1234, 10000}); + assertEquals("[1,2,50,1234,10000]", s); + } - assertEquals(o.get("key1"), "v1"); - assertEquals(((JSONObject) o.get("key2")).size(), 0); - assertEquals(((JSONArray) o.get("key3")).size(), 0); - } + @Test + public void testEmptyStrict() throws Exception { + String s = "{\"key1\":\"v1\", \"key2\":{}, \"key3\":[]}"; + JSONObject o = (JSONObject) JSONValue.parseStrict(s); - @Test - public void testBool() throws Exception { - String s = "{\"key1\":\"v1\", \"key2\":{}, \"key3\":[]}"; - JSONObject o = (JSONObject) JSONValue.parseWithException(s); + assertEquals(o.get("key1"), "v1"); + assertEquals(((JSONObject) o.get("key2")).size(), 0); + assertEquals(((JSONArray) o.get("key3")).size(), 0); + } - assertEquals(o.get("key1"), "v1"); - assertEquals(((JSONObject) o.get("key2")).size(), 0); - assertEquals(((JSONArray) o.get("key3")).size(), 0); - } + @Test + public void testBool() throws Exception { + String s = "{\"key1\":\"v1\", \"key2\":{}, \"key3\":[]}"; + JSONObject o = (JSONObject) JSONValue.parseWithException(s); - @Test - public void testInt() throws Exception { - String s = "123"; - Object o = JSONValue.parseWithException(s); - assertEquals(o, 123); - } + assertEquals(o.get("key1"), "v1"); + assertEquals(((JSONObject) o.get("key2")).size(), 0); + assertEquals(((JSONArray) o.get("key3")).size(), 0); + } - @Test - public void testFloat() throws Exception { - String s = "123.5"; - Object o = JSONValue.parseWithException(s); - assertEquals(o, Double.valueOf(123.5)); - } + @Test + public void testInt() throws Exception { + String s = "123"; + Object o = JSONValue.parseWithException(s); + assertEquals(o, 123); + } - @Test - public void testFloat2() throws Exception { - String s = "123.5E1"; - Object o = JSONValue.parseWithException(s); - assertEquals(o, Double.valueOf(1235)); - } + @Test + public void testFloat() throws Exception { + String s = "123.5"; + Object o = JSONValue.parseWithException(s); + assertEquals(o, Double.valueOf(123.5)); + } - @Test - public void testFloat3() throws Exception { - String s = "123..5"; - Object o = JSONValue.parseWithException(s); - assertEquals(o, "123..5"); - } + @Test + public void testFloat2() throws Exception { + String s = "123.5E1"; + Object o = JSONValue.parseWithException(s); + assertEquals(o, Double.valueOf(1235)); + } - @Test - public void testFloat4() throws Exception { - String s = "123é.5"; - Object o = JSONValue.parseWithException(s); - assertEquals(o, 123); - } + @Test + public void testFloat3() throws Exception { + String s = "123..5"; + Object o = JSONValue.parseWithException(s); + assertEquals(o, "123..5"); + } + @Test + public void testFloat4() throws Exception { + String s = "123é.5"; + Object o = JSONValue.parseWithException(s); + assertEquals(o, 123); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestNavi.java b/json-smart/src/test/java/net/minidev/json/test/TestNavi.java index 63345d2..040e660 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestNavi.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestNavi.java @@ -1,61 +1,99 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import net.minidev.json.JSONAwareEx; import net.minidev.json.JSONNavi; - import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; public class TestNavi { - @Test - public void testNaviWrite() { - JSONNavi nav = JSONNavi.newInstance(); - nav.set("name", "jhone").set("age", 42).at("childName").add("fifi", "riri", "loulou").up().at("cat") - .set("color", "red"); - String s1 = "{\"name\":\"jhone\",\"age\":42,\"childName\":[\"fifi\",\"riri\",\"loulou\"],\"cat\":{\"color\":\"red\"}}"; - String s2 = nav.toString(); - assertEquals(s1, s2); - } + @Test + public void testNaviWrite() { + JSONNavi nav = JSONNavi.newInstance(); + nav.set("name", "jhone") + .set("age", 42) + .at("childName") + .add("fifi", "riri", "loulou") + .up() + .at("cat") + .set("color", "red"); + String s1 = + "{\"name\":\"jhone\",\"age\":42,\"childName\":[\"fifi\",\"riri\",\"loulou\"],\"cat\":{\"color\":\"red\"}}"; + String s2 = nav.toString(); + assertEquals(s1, s2); + } + + @Test + public void testNaviWrite2() { + JSONNavi nav = JSONNavi.newInstance(); + nav.at("name") + .set("toto") + .up() + .set("tutu", "V2") + .at("size") + .set("width", 10) + .set("higth", 35) + .up(3) + .set("FinUp", 1) + .at("array") + .add(0, 1, 2, 3, 4, 5); + nav.at(-1); + assertEquals("/array[5]", nav.getJPath()); + String s1 = + "{'name':'toto','tutu':'V2','size':{'width':10,'higth':35},'FinUp':1,'array':[0,1,2,3,4,5]}" + .replace('\'', '"'); + String s2 = nav.toString(); + assertEquals(s1, s2); + } + + @Test + public void testNaviRead() { + String json = "{name:foo,str:null,ar:[1,2,3,4]}"; + JSONNavi nav = new JSONNavi(json, JSONAwareEx.class); + nav.at(5); + assertTrue(nav.hasFailure(), "Navigator should be in error stat"); + nav.root(); + assertEquals(3, nav.at("ar").at(2).asInt()); + nav.up(2); + assertEquals(4, nav.at("ar").at(-1).asInt()); + nav.up(2); + assertEquals("foo", nav.at("name").asString()); + } - @Test - public void testNaviWrite2() { - JSONNavi nav = JSONNavi.newInstance(); - nav.at("name").set("toto").up().set("tutu", "V2").at("size").set("width", 10).set("higth", 35).up(3) - .set("FinUp", 1).at("array").add(0, 1, 2, 3, 4, 5); - nav.at(-1); - assertEquals("/array[5]", nav.getJPath()); - String s1 = "{'name':'toto','tutu':'V2','size':{'width':10,'higth':35},'FinUp':1,'array':[0,1,2,3,4,5]}" - .replace('\'', '"'); - String s2 = nav.toString(); - assertEquals(s1, s2); - } + @Test + public void testNaviWriteArray() { + String expected = + "{'type':'bundle','data':[{'type':'object','name':'obj1'},{'type':'object','name':'obj2'}]}" + .replace('\'', '"'); + JSONNavi nav = JSONNavi.newInstance(); + nav.set("type", "bundle") + .at("data") + .array() + .at(0) + .set("type", "object") + .set("name", "obj1") + .up() + .at(1) + .set("type", "object") + .set("name", "obj2") + .root(); + String s2 = nav.toString(); + assertEquals(expected, s2); - @Test - public void testNaviRead() { - String json = "{name:foo,str:null,ar:[1,2,3,4]}"; - JSONNavi nav = new JSONNavi(json, JSONAwareEx.class); - nav.at(5); - assertTrue(nav.hasFailure(), "Navigator should be in error stat"); - nav.root(); - assertEquals(3, nav.at("ar").at(2).asInt()); - nav.up(2); - assertEquals(4, nav.at("ar").at(-1).asInt()); - nav.up(2); - assertEquals("foo", nav.at("name").asString()); - } - - @Test - public void testNaviWriteArray() { - String expected = "{'type':'bundle','data':[{'type':'object','name':'obj1'},{'type':'object','name':'obj2'}]}".replace('\'', '"'); - JSONNavi nav = JSONNavi.newInstance(); - nav.set("type", "bundle").at("data").array().at(0).set("type", "object").set("name", "obj1").up().at(1).set("type", "object").set("name", "obj2").root(); - String s2 = nav.toString(); - assertEquals(expected, s2); - - nav = JSONNavi.newInstance(); - nav.set("type", "bundle").at("data").array().atNext().set("type", "object").set("name", "obj1").up().atNext().set("type", "object").set("name", "obj2").root(); - s2 = nav.toString(); - assertEquals(expected, s2); - } + nav = JSONNavi.newInstance(); + nav.set("type", "bundle") + .at("data") + .array() + .atNext() + .set("type", "object") + .set("name", "obj1") + .up() + .atNext() + .set("type", "object") + .set("name", "obj2") + .root(); + s2 = nav.toString(); + assertEquals(expected, s2); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestNumberPrecision.java b/json-smart/src/test/java/net/minidev/json/test/TestNumberPrecision.java index 62c91ee..a9f89a1 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestNumberPrecision.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestNumberPrecision.java @@ -3,46 +3,44 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.math.BigInteger; - import net.minidev.json.JSONArray; import net.minidev.json.JSONValue; - import org.junit.jupiter.api.Test; public class TestNumberPrecision { - @Test - public void testMaxLong() { - Long v = Long.MAX_VALUE; - String s = "[" + v + "]"; - JSONArray array = (JSONArray) JSONValue.parse(s); - Object r = array.get(0); - assertEquals(v, r); - } - - @Test - public void testMinLong() { - Long v = Long.MIN_VALUE; - String s = "[" + v + "]"; - JSONArray array = (JSONArray) JSONValue.parse(s); - Object r = array.get(0); - assertEquals(v, r); - } - - @Test - public void testMinBig() { - BigInteger v = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE); - String s = "[" + v + "]"; - JSONArray array = (JSONArray) JSONValue.parse(s); - Object r = array.get(0); - assertEquals(v, r); - } - - @Test - public void testMaxBig() { - BigInteger v = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); - String s = "[" + v + "]"; - JSONArray array = (JSONArray) JSONValue.parse(s); - Object r = array.get(0); - assertEquals(v, r); - } + @Test + public void testMaxLong() { + Long v = Long.MAX_VALUE; + String s = "[" + v + "]"; + JSONArray array = (JSONArray) JSONValue.parse(s); + Object r = array.get(0); + assertEquals(v, r); + } + + @Test + public void testMinLong() { + Long v = Long.MIN_VALUE; + String s = "[" + v + "]"; + JSONArray array = (JSONArray) JSONValue.parse(s); + Object r = array.get(0); + assertEquals(v, r); + } + + @Test + public void testMinBig() { + BigInteger v = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE); + String s = "[" + v + "]"; + JSONArray array = (JSONArray) JSONValue.parse(s); + Object r = array.get(0); + assertEquals(v, r); + } + + @Test + public void testMaxBig() { + BigInteger v = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); + String s = "[" + v + "]"; + JSONArray array = (JSONArray) JSONValue.parse(s); + Object r = array.get(0); + assertEquals(v, r); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java b/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java index 9dd3541..306d0f4 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java @@ -1,72 +1,71 @@ package net.minidev.json.test; -import net.minidev.json.JSONArray; -import net.minidev.json.JSONValue; -import net.minidev.json.parser.JSONParser; -import net.minidev.json.parser.ParseException; - import static net.minidev.json.parser.JSONParser.DEFAULT_PERMISSIVE_MODE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONValue; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; import org.junit.jupiter.api.Test; public class TestOverflow { - @Test - public void stressTest() throws Exception { - int size = 10000; - StringBuilder sb = new StringBuilder(10 + size*4); - for (int i=0; i < size; i++) { - sb.append("{a:"); - } - sb.append("true"); - for (int i=0; i < size; i++) { - sb.append("}"); - } - String s = sb.toString(); - try { - JSONValue.parseWithException(s); - } catch (ParseException e) { - assertEquals(e.getErrorType(), ParseException.ERROR_UNEXPECTED_JSON_DEPTH); - return; - } - fail(); - } + @Test + public void stressTest() throws Exception { + int size = 10000; + StringBuilder sb = new StringBuilder(10 + size * 4); + for (int i = 0; i < size; i++) { + sb.append("{a:"); + } + sb.append("true"); + for (int i = 0; i < size; i++) { + sb.append("}"); + } + String s = sb.toString(); + try { + JSONValue.parseWithException(s); + } catch (ParseException e) { + assertEquals(e.getErrorType(), ParseException.ERROR_UNEXPECTED_JSON_DEPTH); + return; + } + fail(); + } - @Test - public void shouldNotFailWhenInfiniteJsonDepth() throws Exception { - int size = 500; - StringBuilder sb = new StringBuilder(10 + size*4); - for (int i=0; i < size; i++) { - sb.append("{a:"); - } - sb.append("true"); - for (int i=0; i < size; i++) { - sb.append("}"); - } - String s = sb.toString(); - try { - JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE & ~JSONParser.LIMIT_JSON_DEPTH); - parser.parse(s, JSONValue.defaultReader.DEFAULT); - } catch (ParseException e) { - fail(); - } - } + @Test + public void shouldNotFailWhenInfiniteJsonDepth() throws Exception { + int size = 500; + StringBuilder sb = new StringBuilder(10 + size * 4); + for (int i = 0; i < size; i++) { + sb.append("{a:"); + } + sb.append("true"); + for (int i = 0; i < size; i++) { + sb.append("}"); + } + String s = sb.toString(); + try { + JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE & ~JSONParser.LIMIT_JSON_DEPTH); + parser.parse(s, JSONValue.defaultReader.DEFAULT); + } catch (ParseException e) { + fail(); + } + } - @Test - public void shouldNotFailParsingArraysWith400Elements() throws Exception { - int size = 400; - StringBuilder sb = new StringBuilder(); - sb.append("["); - for (int i=0; i < size; i++) { - sb.append("{a:true}"); - if(i+1 < size) { - sb.append(","); - } - } - sb.append("]"); - String s = sb.toString(); - JSONArray array = (JSONArray) JSONValue.parseWithException(s); - assertEquals(array.size(), size); - } + @Test + public void shouldNotFailParsingArraysWith400Elements() throws Exception { + int size = 400; + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (int i = 0; i < size; i++) { + sb.append("{a:true}"); + if (i + 1 < size) { + sb.append(","); + } + } + sb.append("]"); + String s = sb.toString(); + JSONArray array = (JSONArray) JSONValue.parseWithException(s); + assertEquals(array.size(), size); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestStrict.java b/json-smart/src/test/java/net/minidev/json/test/TestStrict.java index b41ae73..b3fd9d9 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestStrict.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestStrict.java @@ -1,59 +1,59 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; + import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; public class TestStrict { - @Test - public void testS1() throws Exception { - String text = "My Test"; - String s = "{t:\"" + text + "\"}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), text); - } - - @Test - public void testS2() throws Exception { - String text = "My Test"; - String s = "{t:'" + text + "'}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), text); - } - - @Test - public void testSEscape() throws Exception { - String text = "My\r\nTest"; - String text2 = "My\\r\\nTest"; - String s = "{t:'" + text2 + "'}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), text); - } - - @Test - public void testBadString() throws Exception { - String s = "{\"t\":\"Before\u000CAfter\"}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals("Before\u000CAfter", o.get("t")); - try { - o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - assertEquals("nothink", o.get("t")); - } catch (ParseException e) { - assertEquals("Exception", "Exception"); - } - } - - /** - * issue report gitHub 8 by jochenberger - */ - @Test - public void testDataAfterValue() throws Exception { - String s = "{\"foo\":\"bar\"x}"; - MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE, ParseException.ERROR_UNEXPECTED_TOKEN); - } + @Test + public void testS1() throws Exception { + String text = "My Test"; + String s = "{t:\"" + text + "\"}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), text); + } + + @Test + public void testS2() throws Exception { + String text = "My Test"; + String s = "{t:'" + text + "'}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), text); + } + + @Test + public void testSEscape() throws Exception { + String text = "My\r\nTest"; + String text2 = "My\\r\\nTest"; + String s = "{t:'" + text2 + "'}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), text); + } + + @Test + public void testBadString() throws Exception { + String s = "{\"t\":\"Before\u000CAfter\"}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals("Before\u000CAfter", o.get("t")); + try { + o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + assertEquals("nothink", o.get("t")); + } catch (ParseException e) { + assertEquals("Exception", "Exception"); + } + } + + /** issue report gitHub 8 by jochenberger */ + @Test + public void testDataAfterValue() throws Exception { + String s = "{\"foo\":\"bar\"x}"; + MustThrows.testInvalidJson( + s, + JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE, + ParseException.ERROR_UNEXPECTED_TOKEN); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestString.java b/json-smart/src/test/java/net/minidev/json/test/TestString.java index b925486..51e4f42 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestString.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestString.java @@ -1,55 +1,55 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; + import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; public class TestString { - @Test - public void testS0() throws Exception { - MustThrows.testStrictInvalidJson("{\"1\":\"one\"\n\"2\":\"two\"}", ParseException.ERROR_UNEXPECTED_TOKEN); - } - - @Test - public void testS1() throws Exception { - String text = "My Test"; - String s = "{t:\"" + text + "\"}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), text); - } - - @Test - public void testS2() throws Exception { - String text = "My Test"; - String s = "{t:'" + text + "'}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), text); - } - - @Test - public void testSEscape() throws Exception { - String text = "My\r\nTest"; - String text2 = "My\\r\\nTest"; - String s = "{t:'" + text2 + "'}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), text); - } - - @Test - public void testBadString() throws Exception { - String s = "{\"t\":\"Before\u000CAfter\"}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals("Before\u000CAfter", o.get("t")); - try { - o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - assertEquals("nothink", o.get("t")); - } catch (ParseException e) { - assertEquals("Exception", "Exception"); - } - } + @Test + public void testS0() throws Exception { + MustThrows.testStrictInvalidJson( + "{\"1\":\"one\"\n\"2\":\"two\"}", ParseException.ERROR_UNEXPECTED_TOKEN); + } + + @Test + public void testS1() throws Exception { + String text = "My Test"; + String s = "{t:\"" + text + "\"}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), text); + } + + @Test + public void testS2() throws Exception { + String text = "My Test"; + String s = "{t:'" + text + "'}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), text); + } + + @Test + public void testSEscape() throws Exception { + String text = "My\r\nTest"; + String text2 = "My\\r\\nTest"; + String s = "{t:'" + text2 + "'}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), text); + } + + @Test + public void testBadString() throws Exception { + String s = "{\"t\":\"Before\u000CAfter\"}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals("Before\u000CAfter", o.get("t")); + try { + o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + assertEquals("nothink", o.get("t")); + } catch (ParseException e) { + assertEquals("Exception", "Exception"); + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestStringStrict.java b/json-smart/src/test/java/net/minidev/json/test/TestStringStrict.java index c8fb77f..2c0f64b 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestStringStrict.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestStringStrict.java @@ -1,22 +1,21 @@ package net.minidev.json.test; -import org.junit.jupiter.api.Test; - import net.minidev.json.parser.ParseException; +import org.junit.jupiter.api.Test; public class TestStringStrict { - @Test - public void testS1() throws Exception { - String text = "My Test"; - String s = "{t:\"" + text + "\"}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_TOKEN); - } - - @Test - public void testSEscape() throws Exception { - String text2 = "My\\r\\nTest"; - String s = "{\"t\":'" + text2 + "'}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - } + @Test + public void testS1() throws Exception { + String text = "My Test"; + String s = "{t:\"" + text + "\"}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_TOKEN); + } + + @Test + public void testSEscape() throws Exception { + String text2 = "My\\r\\nTest"; + String s = "{\"t\":'" + text2 + "'}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestTruncated.java b/json-smart/src/test/java/net/minidev/json/test/TestTruncated.java index 8c6ea83..66081cf 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestTruncated.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestTruncated.java @@ -1,26 +1,25 @@ package net.minidev.json.test; import net.minidev.json.parser.ParseException; - import org.junit.jupiter.api.Test; public class TestTruncated { - @Test - public void testS1() throws Exception { - String s = "{\"key\":{}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_EOF); - } + @Test + public void testS1() throws Exception { + String s = "{\"key\":{}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_EOF); + } - @Test - public void testS2() throws Exception { - String s = "{\"key\":"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_EOF); - } + @Test + public void testS2() throws Exception { + String s = "{\"key\":"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_EOF); + } - @Test - public void testS3() throws Exception { - String s = "{\"key\":123"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_EOF); - } + @Test + public void testS3() throws Exception { + String s = "{\"key\":123"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_EOF); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/TestUtf8.java b/json-smart/src/test/java/net/minidev/json/test/TestUtf8.java index 234314d..03203fd 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestUtf8.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestUtf8.java @@ -1,66 +1,77 @@ package net.minidev.json.test; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.io.ByteArrayInputStream; import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.util.stream.Stream; - import net.minidev.json.JSONObject; import net.minidev.json.JSONValue; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; public class TestUtf8 { - public static Stream languages() { - return Stream.of(Arguments.of("Sinhala", "සිංහල ජාතිය"), Arguments.of("Japanese", "日本語"), - Arguments.of("Russian", "Русский"), Arguments.of("Farsi", "فارسی"), Arguments.of("Korean", "한국어"), - Arguments.of("Armenian", "Հայերեն"), Arguments.of("Hindi", "हिन्दी"), Arguments.of("Hebrew", "עברית"), - Arguments.of("Chinese", "中文"), Arguments.of("Amharic", "አማርኛ"), Arguments.of("Malayalam", "മലയാളം"), - Arguments.of("Assyrian Neo-Aramaic", "ܐܬܘܪܝܐ"), Arguments.of("Georgian", "მარგალური"), - Arguments.of("Emojis", "🐶🐱🐭🐹🐰🦊🐻🐼🐻‍❄🐨🐯🦁🐮🐷🐽🐸🐵🙈🙉🙊🐒🐔🐧🐦🐤🐣🐥🦆🦅🦉🦇🐺🐗🐴🦄🐝🐛")); - }; + public static Stream languages() { + return Stream.of( + Arguments.of("Sinhala", "සිංහල ජාතිය"), + Arguments.of("Japanese", "日本語"), + Arguments.of("Russian", "Русский"), + Arguments.of("Farsi", "فارسی"), + Arguments.of("Korean", "한국어"), + Arguments.of("Armenian", "Հայերեն"), + Arguments.of("Hindi", "हिन्दी"), + Arguments.of("Hebrew", "עברית"), + Arguments.of("Chinese", "中文"), + Arguments.of("Amharic", "አማርኛ"), + Arguments.of("Malayalam", "മലയാളം"), + Arguments.of("Assyrian Neo-Aramaic", "ܐܬܘܪܝܐ"), + Arguments.of("Georgian", "მარგალური"), + Arguments.of( + "Emojis", + "🐶🐱🐭🐹🐰🦊🐻🐼🐻‍❄🐨🐯🦁🐮🐷🐽🐸🐵🙈🙉🙊🐒🐔🐧🐦🐤🐣🐥🦆🦅🦉🦇🐺🐗🐴🦄🐝🐛")); + } + ; - @ParameterizedTest - @MethodSource("languages") - public void supportI18nString(String language, String nonLatinText) throws Exception { - String json = "{\"key\":\"" + nonLatinText + "\"}"; - JSONObject obj = (JSONObject) JSONValue.parse(json); - String actual = (String) obj.get("key"); - assertEquals(nonLatinText, actual, "Parsing String " + language + " text"); - } + @ParameterizedTest + @MethodSource("languages") + public void supportI18nString(String language, String nonLatinText) throws Exception { + String json = "{\"key\":\"" + nonLatinText + "\"}"; + JSONObject obj = (JSONObject) JSONValue.parse(json); + String actual = (String) obj.get("key"); + assertEquals(nonLatinText, actual, "Parsing String " + language + " text"); + } - @ParameterizedTest - @MethodSource("languages") - public void supportI18nStringReader(String language, String nonLatinText) throws Exception { - String json = "{\"key\":\"" + nonLatinText + "\"}"; - StringReader reader = new StringReader(json); - JSONObject obj = (JSONObject) JSONValue.parse(reader); + @ParameterizedTest + @MethodSource("languages") + public void supportI18nStringReader(String language, String nonLatinText) throws Exception { + String json = "{\"key\":\"" + nonLatinText + "\"}"; + StringReader reader = new StringReader(json); + JSONObject obj = (JSONObject) JSONValue.parse(reader); - String actual = (String) obj.get("key"); - assertEquals(nonLatinText, actual, "Parsing StringReader " + language + " text"); - } + String actual = (String) obj.get("key"); + assertEquals(nonLatinText, actual, "Parsing StringReader " + language + " text"); + } - @ParameterizedTest - @MethodSource("languages") - public void supportI18nByteArrayInputStream(String language, String nonLatinText) throws Exception { - String json = "{\"key\":\"" + nonLatinText + "\"}"; - ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)); - JSONObject obj = (JSONObject) JSONValue.parse(bis); - String actual = (String) obj.get("key"); - assertEquals(nonLatinText, actual, "Parsing ByteArrayInputStream " + language + " text"); - } + @ParameterizedTest + @MethodSource("languages") + public void supportI18nByteArrayInputStream(String language, String nonLatinText) + throws Exception { + String json = "{\"key\":\"" + nonLatinText + "\"}"; + ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)); + JSONObject obj = (JSONObject) JSONValue.parse(bis); + String actual = (String) obj.get("key"); + assertEquals(nonLatinText, actual, "Parsing ByteArrayInputStream " + language + " text"); + } - @ParameterizedTest - @MethodSource("languages") - public void supportI18nBytes(String language, String nonLatinText) throws Exception { - String json = "{\"key\":\"" + nonLatinText + "\"}"; - byte[] bs = json.getBytes(StandardCharsets.UTF_8); - JSONObject obj = JSONValue.parse(bs, JSONObject.class); - String actual = (String) obj.get("key"); - assertEquals(nonLatinText, actual, "Parsing bytes[] " + language + " text"); - } -} \ No newline at end of file + @ParameterizedTest + @MethodSource("languages") + public void supportI18nBytes(String language, String nonLatinText) throws Exception { + String json = "{\"key\":\"" + nonLatinText + "\"}"; + byte[] bs = json.getBytes(StandardCharsets.UTF_8); + JSONObject obj = JSONValue.parse(bs, JSONObject.class); + String actual = (String) obj.get("key"); + assertEquals(nonLatinText, actual, "Parsing bytes[] " + language + " text"); + } +} diff --git a/json-smart/src/test/java/net/minidev/json/test/strict/TestExcessiveComma.java b/json-smart/src/test/java/net/minidev/json/test/strict/TestExcessiveComma.java index 22a613f..ae537ec 100644 --- a/json-smart/src/test/java/net/minidev/json/test/strict/TestExcessiveComma.java +++ b/json-smart/src/test/java/net/minidev/json/test/strict/TestExcessiveComma.java @@ -3,56 +3,55 @@ import net.minidev.json.JSONValue; import net.minidev.json.parser.ParseException; import net.minidev.json.test.MustThrows; - import org.junit.jupiter.api.Test; public class TestExcessiveComma { - @Test - public void testExcessiveComma1A() throws Exception { - String s = "[1,2,,3]"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - JSONValue.parseWithException(s); - } - - @Test - public void testExcessiveComma2A() throws Exception { - String s = "[1,2,]"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - JSONValue.parseWithException(s); - } - - @Test - public void testExcessiveComma3A() throws Exception { - String s = "[,]"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - JSONValue.parseWithException(s); - } - - @Test - public void testExcessiveComma4A() throws Exception { - String s = "[,5]"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - JSONValue.parseWithException(s); - } - - @Test - public void testExcessiveComma1O() throws Exception { - String s = "{\"a\":1,,\"b\":1}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - JSONValue.parseWithException(s); - } - - @Test - public void testExcessiveComma2O() throws Exception { - String s = "{\"a\":1,}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - JSONValue.parseWithException(s); - } - - @Test - public void testExcessiveComma3O() throws Exception { - String s = "{,}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); - JSONValue.parseWithException(s); - } + @Test + public void testExcessiveComma1A() throws Exception { + String s = "[1,2,,3]"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + JSONValue.parseWithException(s); + } + + @Test + public void testExcessiveComma2A() throws Exception { + String s = "[1,2,]"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + JSONValue.parseWithException(s); + } + + @Test + public void testExcessiveComma3A() throws Exception { + String s = "[,]"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + JSONValue.parseWithException(s); + } + + @Test + public void testExcessiveComma4A() throws Exception { + String s = "[,5]"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + JSONValue.parseWithException(s); + } + + @Test + public void testExcessiveComma1O() throws Exception { + String s = "{\"a\":1,,\"b\":1}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + JSONValue.parseWithException(s); + } + + @Test + public void testExcessiveComma2O() throws Exception { + String s = "{\"a\":1,}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + JSONValue.parseWithException(s); + } + + @Test + public void testExcessiveComma3O() throws Exception { + String s = "{,}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_CHAR); + JSONValue.parseWithException(s); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/strict/TestSpecialChar.java b/json-smart/src/test/java/net/minidev/json/test/strict/TestSpecialChar.java index 3041332..22c4c73 100644 --- a/json-smart/src/test/java/net/minidev/json/test/strict/TestSpecialChar.java +++ b/json-smart/src/test/java/net/minidev/json/test/strict/TestSpecialChar.java @@ -2,34 +2,32 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - import net.minidev.json.JSONArray; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; import net.minidev.json.test.MustThrows; +import org.junit.jupiter.api.Test; + /** * Test control charaters - * - * @author uriel * + * @author uriel */ public class TestSpecialChar { - - @Test - public void testSpecial127() throws Exception { - String s127 = String.format("%c", 127); - String s = String.format("[\"%c\"]", 127); - MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_CHAR); - - JSONArray o = (JSONArray) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - assertEquals(o.get(0), s127); - } - @Test - public void testSpecial31() throws Exception { - String s = String.format("[\"%c\"]", 31); - MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_CHAR); - } + @Test + public void testSpecial127() throws Exception { + String s127 = String.format("%c", 127); + String s = String.format("[\"%c\"]", 127); + MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_CHAR); + + JSONArray o = (JSONArray) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + assertEquals(o.get(0), s127); + } + @Test + public void testSpecial31() throws Exception { + String s = String.format("[\"%c\"]", 31); + MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_CHAR); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/strict/TestTaillingJunk.java b/json-smart/src/test/java/net/minidev/json/test/strict/TestTaillingJunk.java index c710b7f..84811a9 100644 --- a/json-smart/src/test/java/net/minidev/json/test/strict/TestTaillingJunk.java +++ b/json-smart/src/test/java/net/minidev/json/test/strict/TestTaillingJunk.java @@ -1,12 +1,11 @@ package net.minidev.json.test.strict; +import static org.junit.jupiter.api.Assertions.assertEquals; + import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; import net.minidev.json.test.MustThrows; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; /** @@ -14,39 +13,47 @@ */ public class TestTaillingJunk { - @Test - public void testTaillingSpace() throws Exception { - String s = "{\"t\":0} "; - MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_TOKEN); - - s = "{\"t\":0} "; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE).parse(s); - assertEquals(o.get("t"), 0); - } - - @Test - public void testTaillingSpace2() throws Exception { - String s = "{\"t\":0} \r\n "; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE).parse(s); - assertEquals(o.get("t"), 0); - } - - @Test - public void testTaillingData() throws Exception { - String s = "{\"t\":0} 0"; - MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_TOKEN, null); - } - - @Test - public void testTaillingDataPermisive() throws Exception { - String s = "{\"t\":0} 0"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), 0); - } - - @Test - public void testTaillingDataWithSpaceAllowed() throws Exception { - String s = "{\"t\":0}{"; - MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE, ParseException.ERROR_UNEXPECTED_TOKEN); - } + @Test + public void testTaillingSpace() throws Exception { + String s = "{\"t\":0} "; + MustThrows.testInvalidJson(s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_TOKEN); + + s = "{\"t\":0} "; + JSONObject o = + (JSONObject) + new JSONParser(JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE).parse(s); + assertEquals(o.get("t"), 0); + } + + @Test + public void testTaillingSpace2() throws Exception { + String s = "{\"t\":0} \r\n "; + JSONObject o = + (JSONObject) + new JSONParser(JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE).parse(s); + assertEquals(o.get("t"), 0); + } + + @Test + public void testTaillingData() throws Exception { + String s = "{\"t\":0} 0"; + MustThrows.testInvalidJson( + s, JSONParser.MODE_STRICTEST, ParseException.ERROR_UNEXPECTED_TOKEN, null); + } + + @Test + public void testTaillingDataPermisive() throws Exception { + String s = "{\"t\":0} 0"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), 0); + } + + @Test + public void testTaillingDataWithSpaceAllowed() throws Exception { + String s = "{\"t\":0}{"; + MustThrows.testInvalidJson( + s, + JSONParser.MODE_STRICTEST | JSONParser.ACCEPT_TAILLING_SPACE, + ParseException.ERROR_UNEXPECTED_TOKEN); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/strict/TestZeroLead.java b/json-smart/src/test/java/net/minidev/json/test/strict/TestZeroLead.java index 723e613..bbe9466 100644 --- a/json-smart/src/test/java/net/minidev/json/test/strict/TestZeroLead.java +++ b/json-smart/src/test/java/net/minidev/json/test/strict/TestZeroLead.java @@ -1,14 +1,13 @@ package net.minidev.json.test.strict; +import static org.junit.jupiter.api.Assertions.assertEquals; + import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.JSONValue; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; import net.minidev.json.test.MustThrows; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; /** @@ -16,52 +15,52 @@ */ public class TestZeroLead { - @Test - public void test0O() throws Exception { - String s = "{\"t\":0}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - assertEquals(o.get("t"), 0); - JSONValue.parseWithException(s); - } + @Test + public void test0O() throws Exception { + String s = "{\"t\":0}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + assertEquals(o.get("t"), 0); + JSONValue.parseWithException(s); + } - @Test - public void test0A() throws Exception { - String s = "[0]"; - JSONArray o = (JSONArray) new JSONParser(JSONParser.MODE_RFC4627).parse(s); - assertEquals(o.get(0), 0); - JSONValue.parseWithException(s); - } + @Test + public void test0A() throws Exception { + String s = "[0]"; + JSONArray o = (JSONArray) new JSONParser(JSONParser.MODE_RFC4627).parse(s); + assertEquals(o.get(0), 0); + JSONValue.parseWithException(s); + } - @Test - public void test0Float() throws Exception { - String s = "[00.0]"; - // strict - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_LEADING_0); - // PERMISIVE - JSONValue.parseWithException(s); - } + @Test + public void test0Float() throws Exception { + String s = "[00.0]"; + // strict + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_LEADING_0); + // PERMISIVE + JSONValue.parseWithException(s); + } - @Test - public void test01Float() throws Exception { - String s = "[01.0]"; - // strict - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_LEADING_0); - // PERMISIVE - JSONValue.parseWithException(s); - } + @Test + public void test01Float() throws Exception { + String s = "[01.0]"; + // strict + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_LEADING_0); + // PERMISIVE + JSONValue.parseWithException(s); + } - @Test - public void test00001() throws Exception { - String s = "{\"t\":00001}"; - JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); - assertEquals(o.get("t"), 1); - JSONValue.parseWithException(s); - } + @Test + public void test00001() throws Exception { + String s = "{\"t\":00001}"; + JSONObject o = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE).parse(s); + assertEquals(o.get("t"), 1); + JSONValue.parseWithException(s); + } - @Test - public void test00001Strict() throws Exception { - String s = "{\"t\":00001}"; - MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_LEADING_0); - JSONValue.parseWithException(s); - } + @Test + public void test00001Strict() throws Exception { + String s = "{\"t\":00001}"; + MustThrows.testStrictInvalidJson(s, ParseException.ERROR_UNEXPECTED_LEADING_0); + JSONValue.parseWithException(s); + } } diff --git a/json-smart/src/test/java/net/minidev/json/test/writer/TestWriteFeatures.java b/json-smart/src/test/java/net/minidev/json/test/writer/TestWriteFeatures.java index 21d0511..3a4035f 100644 --- a/json-smart/src/test/java/net/minidev/json/test/writer/TestWriteFeatures.java +++ b/json-smart/src/test/java/net/minidev/json/test/writer/TestWriteFeatures.java @@ -2,31 +2,30 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.jupiter.api.Test; - import net.minidev.json.JSONStyle; import net.minidev.json.JSONValue; +import org.junit.jupiter.api.Test; public class TestWriteFeatures { - @Test - public void testS1() throws Exception { - Beans beans = new Beans(); - String s = JSONValue.toJSONString(beans, JSONStyle.MAX_COMPRESS); - assertEquals("{}", s); - s = JSONValue.toJSONString(beans, JSONStyle.NO_COMPRESS); - if (s.startsWith("{\"b")) { - assertEquals("{\"b\":null,\"a\":null}", s); - } else { - assertEquals("{\"a\":null,\"b\":null}", s); - } - beans.a = "a"; - s = JSONValue.toJSONString(beans, JSONStyle.MAX_COMPRESS); - assertEquals("{a:a}", s); - } + @Test + public void testS1() throws Exception { + Beans beans = new Beans(); + String s = JSONValue.toJSONString(beans, JSONStyle.MAX_COMPRESS); + assertEquals("{}", s); + s = JSONValue.toJSONString(beans, JSONStyle.NO_COMPRESS); + if (s.startsWith("{\"b")) { + assertEquals("{\"b\":null,\"a\":null}", s); + } else { + assertEquals("{\"a\":null,\"b\":null}", s); + } + beans.a = "a"; + s = JSONValue.toJSONString(beans, JSONStyle.MAX_COMPRESS); + assertEquals("{a:a}", s); + } - public static class Beans { - public String a; - public String b; - } + public static class Beans { + public String a; + public String b; + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestAdvancedMapper.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestAdvancedMapper.java index d08ebc5..7101767 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestAdvancedMapper.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestAdvancedMapper.java @@ -4,36 +4,33 @@ import java.text.SimpleDateFormat; import java.util.Date; - -import org.junit.jupiter.api.Test; - import net.minidev.asm.BeansAccessConfig; import net.minidev.json.JSONValue; +import org.junit.jupiter.api.Test; public class TestAdvancedMapper { - public static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); - - @Test - public void testCustomBean() throws Exception { - BeansAccessConfig.addTypeMapper(Object.class, MyLocalConverterot.class); - String s = "{'val':2,'date':'19/04/2010'}"; - TestBean r = JSONValue.parseWithException(s, TestBean.class); - assertEquals("19/04/2010", sdf.format(r.date)); - } - - public static class TestBean { - public int val; - public Date date; - } - - public static class MyLocalConverterot { - - public static Date fromString(Object text) throws Exception { - if (text == null) - return null; - synchronized (sdf) { - return sdf.parse(text.toString()); - } - } - } + public static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + + @Test + public void testCustomBean() throws Exception { + BeansAccessConfig.addTypeMapper(Object.class, MyLocalConverterot.class); + String s = "{'val':2,'date':'19/04/2010'}"; + TestBean r = JSONValue.parseWithException(s, TestBean.class); + assertEquals("19/04/2010", sdf.format(r.date)); + } + + public static class TestBean { + public int val; + public Date date; + } + + public static class MyLocalConverterot { + + public static Date fromString(Object text) throws Exception { + if (text == null) return null; + synchronized (sdf) { + return sdf.parse(text.toString()); + } + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestCustomMappingInstant.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestCustomMappingInstant.java index abe349f..b6b0ad5 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestCustomMappingInstant.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestCustomMappingInstant.java @@ -4,71 +4,74 @@ import java.io.IOException; import java.time.Instant; - import net.minidev.json.JSONStyle; import net.minidev.json.JSONValue; import net.minidev.json.parser.ParseException; import net.minidev.json.writer.JsonReaderI; - import org.junit.jupiter.api.Test; /** * Test JDK 8+ java.time.Instant * - * Serialize a custom class Sample 1 - * - * @author uriel + *

Serialize a custom class Sample 1 * + * @author uriel */ public class TestCustomMappingInstant { - - @Test - public void test_dummy() throws IOException { - @SuppressWarnings("unused") - ParseException e = null; - JSONValue.toJSONString(true, JSONStyle.MAX_COMPRESS); - } - - public void test_instant() { - JSONValue.registerWriter(java.time.Instant.class, new net.minidev.json.reader.JsonWriterI() { - @Override - public void writeJSONString(java.time.Instant value, Appendable out, JSONStyle compression) - throws IOException { - if (value == null) - out.append("null"); - else - out.append(Long.toString(value.toEpochMilli())); - } - }); - - JSONValue.registerReader(RegularClass.class, new JsonReaderI(JSONValue.defaultReader) { - @Override - public void setValue(Object current, String key, Object value) throws ParseException, IOException { - if (key.equals("instant")) { - Instant inst = Instant.ofEpochMilli((((Number)value).longValue())); - ((RegularClass)current).setInstant(inst); - } - } - @Override - public Object createObject() { - return new RegularClass(); - } - }); - Instant instant = Instant.now(); - RegularClass regularClass = new RegularClass(); - regularClass.setInstant(instant); - String data = JSONValue.toJSONString(regularClass); - RegularClass result = JSONValue.parse(data, RegularClass.class); - assertEquals(result.getInstant(), instant); - } - public static class RegularClass { - private java.time.Instant instant; - public java.time.Instant getInstant() { - return instant; - } - public void setInstant(java.time.Instant instant) { - this.instant = instant; - } - } + @Test + public void test_dummy() throws IOException { + @SuppressWarnings("unused") + ParseException e = null; + JSONValue.toJSONString(true, JSONStyle.MAX_COMPRESS); + } + + public void test_instant() { + JSONValue.registerWriter( + java.time.Instant.class, + new net.minidev.json.reader.JsonWriterI() { + @Override + public void writeJSONString( + java.time.Instant value, Appendable out, JSONStyle compression) throws IOException { + if (value == null) out.append("null"); + else out.append(Long.toString(value.toEpochMilli())); + } + }); + + JSONValue.registerReader( + RegularClass.class, + new JsonReaderI(JSONValue.defaultReader) { + @Override + public void setValue(Object current, String key, Object value) + throws ParseException, IOException { + if (key.equals("instant")) { + Instant inst = Instant.ofEpochMilli((((Number) value).longValue())); + ((RegularClass) current).setInstant(inst); + } + } + + @Override + public Object createObject() { + return new RegularClass(); + } + }); + Instant instant = Instant.now(); + RegularClass regularClass = new RegularClass(); + regularClass.setInstant(instant); + String data = JSONValue.toJSONString(regularClass); + RegularClass result = JSONValue.parse(data, RegularClass.class); + assertEquals(result.getInstant(), instant); + } + + public static class RegularClass { + private java.time.Instant instant; + + public java.time.Instant getInstant() { + return instant; + } + + public void setInstant(java.time.Instant instant) { + this.instant = instant; + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestDate.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestDate.java index b4a386b..f319a78 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestDate.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestDate.java @@ -1,26 +1,24 @@ package net.minidev.json.testMapping; -import net.minidev.json.JSONValue; - import static org.junit.jupiter.api.Assertions.assertEquals; +import net.minidev.json.JSONValue; import org.junit.jupiter.api.Test; public class TestDate { - @Test - public void testBooleans() throws Exception { - String s = "[true,true,false]"; - boolean[] bs = new boolean[] { true, true, false }; - String s2 = JSONValue.toJSONString(bs); - assertEquals(s, s2); - } - - @Test - public void testInts() throws Exception { - String s = "[1,2,3]"; - int[] bs = new int[] { 1, 2, 3 }; - String s2 = JSONValue.toJSONString(bs); - assertEquals(s, s2); - } + @Test + public void testBooleans() throws Exception { + String s = "[true,true,false]"; + boolean[] bs = new boolean[] {true, true, false}; + String s2 = JSONValue.toJSONString(bs); + assertEquals(s, s2); + } + @Test + public void testInts() throws Exception { + String s = "[1,2,3]"; + int[] bs = new int[] {1, 2, 3}; + String s2 = JSONValue.toJSONString(bs); + assertEquals(s, s2); + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestFieldRename.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestFieldRename.java index d5a0663..e7a4065 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestFieldRename.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestFieldRename.java @@ -1,30 +1,28 @@ package net.minidev.json.testMapping; -import net.minidev.json.JSONValue; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import net.minidev.json.JSONValue; import org.junit.jupiter.api.Test; public class TestFieldRename { - public static class TRen { - public String new_; - public String default_; - } - - @Test - public void testRemap() throws Exception { - String text = "{'new':'foo','default':'bar'}"; - JSONValue.remapField(TRen.class, "default", "default_"); - JSONValue.remapField(TRen.class, "new", "new_"); - - TRen t = JSONValue.parse(text, TRen.class); - assertEquals(t.new_, "foo"); - assertEquals(t.default_, "bar"); - String dest = JSONValue.toJSONString(t); - assertTrue(dest.contains("\"default\"")); - - } + public static class TRen { + public String new_; + public String default_; + } + + @Test + public void testRemap() throws Exception { + String text = "{'new':'foo','default':'bar'}"; + JSONValue.remapField(TRen.class, "default", "default_"); + JSONValue.remapField(TRen.class, "new", "new_"); + + TRen t = JSONValue.parse(text, TRen.class); + assertEquals(t.new_, "foo"); + assertEquals(t.default_, "bar"); + String dest = JSONValue.toJSONString(t); + assertTrue(dest.contains("\"default\"")); + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapBeans.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapBeans.java index 6faaa20..d54f021 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapBeans.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapBeans.java @@ -1,118 +1,114 @@ package net.minidev.json.testMapping; -import java.util.Map; +import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.Map; import net.minidev.json.JSONValue; - import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; public class TestMapBeans { - @Test - public void testObjInts() throws Exception { - String s = "{\"vint\":[1,2,3]}"; - T1 r = JSONValue.parse(s, T1.class); - assertEquals(3, r.vint[2]); - } - - @Test - public void testObjIntKey() throws Exception { - String s = "{\"data\":{\"1\":\"toto\"}}"; - T2 r = JSONValue.parse(s, T2.class); - assertEquals("toto", r.data.get(1)); - } - - @Test - public void testObjEnumKey() throws Exception { - String s = "{\"data\":{\"red\":10}}"; - T3 r = JSONValue.parse(s, T3.class); - assertEquals((Integer)10, r.data.get(ColorEnum.red)); - } - - @Test - public void testObjBool1() throws Exception { - String s = "{\"data\":true}"; - T4 r = JSONValue.parse(s, T4.class); - assertEquals(true, r.data); - } - - @Test - public void testObjBool2() throws Exception { - String s = "{\"data\":true}"; - T5 r = JSONValue.parse(s, T5.class); - assertEquals(true, r.data); - } - - /** - * class containing primitive array; - */ - public static class T1 { - private int[] vint; - - public int[] getVint() { - return vint; - } - - public void setVint(int[] vint) { - this.vint = vint; - } - } - - /** - * class containing Map interface; - */ - public static class T2 { - private Map data; - - public Map getData() { - return data; - } - - public void setData(Map data) { - this.data = data; - } - } - - public static enum ColorEnum { - bleu, green, red, yellow - } - - public static class T3 { - private Map data; - - public Map getData() { - return data; - } - - public void setData(Map data) { - this.data = data; - } - } - - - public static class T4 { - private boolean data; - - public boolean getData() { - return data; - } - - public void setData(boolean data) { - this.data = data; - } - } - - public static class T5 { - private boolean data; - - public boolean isData() { - return data; - } - - public void setData(boolean data) { - this.data = data; - } - } - + @Test + public void testObjInts() throws Exception { + String s = "{\"vint\":[1,2,3]}"; + T1 r = JSONValue.parse(s, T1.class); + assertEquals(3, r.vint[2]); + } + + @Test + public void testObjIntKey() throws Exception { + String s = "{\"data\":{\"1\":\"toto\"}}"; + T2 r = JSONValue.parse(s, T2.class); + assertEquals("toto", r.data.get(1)); + } + + @Test + public void testObjEnumKey() throws Exception { + String s = "{\"data\":{\"red\":10}}"; + T3 r = JSONValue.parse(s, T3.class); + assertEquals((Integer) 10, r.data.get(ColorEnum.red)); + } + + @Test + public void testObjBool1() throws Exception { + String s = "{\"data\":true}"; + T4 r = JSONValue.parse(s, T4.class); + assertEquals(true, r.data); + } + + @Test + public void testObjBool2() throws Exception { + String s = "{\"data\":true}"; + T5 r = JSONValue.parse(s, T5.class); + assertEquals(true, r.data); + } + + /** class containing primitive array; */ + public static class T1 { + private int[] vint; + + public int[] getVint() { + return vint; + } + + public void setVint(int[] vint) { + this.vint = vint; + } + } + + /** class containing Map interface; */ + public static class T2 { + private Map data; + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + } + + public static enum ColorEnum { + bleu, + green, + red, + yellow + } + + public static class T3 { + private Map data; + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + } + + public static class T4 { + private boolean data; + + public boolean getData() { + return data; + } + + public void setData(boolean data) { + this.data = data; + } + } + + public static class T5 { + private boolean data; + + public boolean isData() { + return data; + } + + public void setData(boolean data) { + this.data = data; + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPrimArrays.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPrimArrays.java index 890c1b9..ff2152e 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPrimArrays.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPrimArrays.java @@ -1,53 +1,52 @@ package net.minidev.json.testMapping; -import net.minidev.json.JSONValue; - import static org.junit.jupiter.api.Assertions.assertEquals; +import net.minidev.json.JSONValue; import org.junit.jupiter.api.Test; public class TestMapPrimArrays { - @Test - public void testInts() throws Exception { - String s = "[1,2,3]"; - int[] r = JSONValue.parse(s, int[].class); - assertEquals(3, r[2]); - } - - @Test - public void testIntss() throws Exception { - String s = "[[1],[2],[3,4]]"; - int[][] r = JSONValue.parse(s, int[][].class); - assertEquals(3, r[2][0]); - assertEquals(4, r[2][1]); - } - - @Test - public void testLongs() throws Exception { - String s = "[1,2,3]"; - long[] r = JSONValue.parse(s, long[].class); - assertEquals(3, r[2]); - } - - @Test - public void testFloat() throws Exception { - String s = "[1.2,22.4,3.14]"; - float[] r = JSONValue.parse(s, float[].class); - assertEquals(3.14F, r[2]); - } - - @Test - public void testDouble() throws Exception { - String s = "[1.2,22.4,3.14]"; - double[] r = JSONValue.parse(s, double[].class); - assertEquals(3.14, r[2]); - } - - @Test - public void testBooleans() throws Exception { - String s = "[true,true,false]"; - boolean[] r = JSONValue.parse(s, boolean[].class); - assertEquals(true, r[1]); - assertEquals(false, r[2]); - } + @Test + public void testInts() throws Exception { + String s = "[1,2,3]"; + int[] r = JSONValue.parse(s, int[].class); + assertEquals(3, r[2]); + } + + @Test + public void testIntss() throws Exception { + String s = "[[1],[2],[3,4]]"; + int[][] r = JSONValue.parse(s, int[][].class); + assertEquals(3, r[2][0]); + assertEquals(4, r[2][1]); + } + + @Test + public void testLongs() throws Exception { + String s = "[1,2,3]"; + long[] r = JSONValue.parse(s, long[].class); + assertEquals(3, r[2]); + } + + @Test + public void testFloat() throws Exception { + String s = "[1.2,22.4,3.14]"; + float[] r = JSONValue.parse(s, float[].class); + assertEquals(3.14F, r[2]); + } + + @Test + public void testDouble() throws Exception { + String s = "[1.2,22.4,3.14]"; + double[] r = JSONValue.parse(s, double[].class); + assertEquals(3.14, r[2]); + } + + @Test + public void testBooleans() throws Exception { + String s = "[true,true,false]"; + boolean[] r = JSONValue.parse(s, boolean[].class); + assertEquals(true, r[1]); + assertEquals(false, r[2]); + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic.java index 670f882..0dd7169 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic.java @@ -4,87 +4,83 @@ import java.util.Map; import java.util.TreeMap; - import net.minidev.json.JSONValue; - import org.junit.jupiter.api.Test; public class TestMapPublic { - @Test - public void testObjInts() throws Exception { - String s = "{\"vint\":[1,2,3]}"; - T1 r = JSONValue.parse(s, T1.class); - assertEquals(3, r.vint[2]); - } - - String MultiTyepJson = "{\"name\":\"B\",\"age\":120,\"cost\":12000,\"flag\":3,\"valid\":true,\"f\":1.2,\"d\":1.5,\"l\":12345678912345}"; + @Test + public void testObjInts() throws Exception { + String s = "{\"vint\":[1,2,3]}"; + T1 r = JSONValue.parse(s, T1.class); + assertEquals(3, r.vint[2]); + } - @Test - public void testObjMixte() throws Exception { - T2 r = JSONValue.parse(MultiTyepJson, T2.class); - assertEquals("B", r.name); - assertEquals(120, r.age); - assertEquals(12000, r.cost); - assertEquals(3, r.flag); - assertEquals(true, r.valid); - assertEquals(1.2F, r.f); - assertEquals(1.5, r.d); - assertEquals(12345678912345L, r.l); - } + String MultiTyepJson = + "{\"name\":\"B\",\"age\":120,\"cost\":12000,\"flag\":3,\"valid\":true,\"f\":1.2,\"d\":1.5,\"l\":12345678912345}"; - @Test - public void testObjMixtePrim() throws Exception { - T3 r = JSONValue.parse(MultiTyepJson, T3.class); - assertEquals("B", r.name); - assertEquals(Short.valueOf((short) 120), r.age); - assertEquals(Integer.valueOf(12000), r.cost); - assertEquals(Byte.valueOf((byte) 3), r.flag); - assertEquals(Boolean.TRUE, r.valid); - assertEquals(1.2F, r.f); - assertEquals(1.5, r.d); - assertEquals(Long.valueOf(12345678912345L), r.l); - } + @Test + public void testObjMixte() throws Exception { + T2 r = JSONValue.parse(MultiTyepJson, T2.class); + assertEquals("B", r.name); + assertEquals(120, r.age); + assertEquals(12000, r.cost); + assertEquals(3, r.flag); + assertEquals(true, r.valid); + assertEquals(1.2F, r.f); + assertEquals(1.5, r.d); + assertEquals(12345678912345L, r.l); + } - public static class T1 { - public int[] vint; - } + @Test + public void testObjMixtePrim() throws Exception { + T3 r = JSONValue.parse(MultiTyepJson, T3.class); + assertEquals("B", r.name); + assertEquals(Short.valueOf((short) 120), r.age); + assertEquals(Integer.valueOf(12000), r.cost); + assertEquals(Byte.valueOf((byte) 3), r.flag); + assertEquals(Boolean.TRUE, r.valid); + assertEquals(1.2F, r.f); + assertEquals(1.5, r.d); + assertEquals(Long.valueOf(12345678912345L), r.l); + } - public static class T2 { - public String name; - public short age; - public int cost; - public byte flag; - public boolean valid; - public float f; - public double d; - public long l; - } + public static class T1 { + public int[] vint; + } - public static class T3 { - public String name; - public Short age; - public Integer cost; - public Byte flag; - public Boolean valid; - public Float f; - public Double d; - public Long l; - } + public static class T2 { + public String name; + public short age; + public int cost; + public byte flag; + public boolean valid; + public float f; + public double d; + public long l; + } - public static class T123 { - public T1 t1; - public T2 t2; - public T3 t3; - } + public static class T3 { + public String name; + public Short age; + public Integer cost; + public Byte flag; + public Boolean valid; + public Float f; + public Double d; + public Long l; + } + public static class T123 { + public T1 t1; + public T2 t2; + public T3 t3; + } - public static class T5 { - public Map data; - } - - public static class T6 { - public TreeMap data; - } + public static class T5 { + public Map data; + } - + public static class T6 { + public TreeMap data; + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic2.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic2.java index b0a19b9..36d848d 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic2.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestMapPublic2.java @@ -4,35 +4,32 @@ import java.util.Map; import java.util.TreeMap; - import net.minidev.json.JSONValue; - import org.junit.jupiter.api.Test; public class TestMapPublic2 { - String s = "{\"data\":{\"a\":\"b\"}}"; - - @Test - public void testMapPublicInterface() throws Exception { - T5 r = JSONValue.parse(s, T5.class); - assertEquals(1, r.data.size()); - } - - @Test - public void testMapPublicMapClass() throws Exception { - T6 r = JSONValue.parse(s, T6.class); - assertEquals(1, r.data.size()); - } - - String MultiTyepJson = "{\"name\":\"B\",\"age\":120,\"cost\":12000,\"flag\":3,\"valid\":true,\"f\":1.2,\"d\":1.5,\"l\":12345678912345}"; - - public static class T5 { - public Map data; - } - - public static class T6 { - public TreeMap data; - } - - + String s = "{\"data\":{\"a\":\"b\"}}"; + + @Test + public void testMapPublicInterface() throws Exception { + T5 r = JSONValue.parse(s, T5.class); + assertEquals(1, r.data.size()); + } + + @Test + public void testMapPublicMapClass() throws Exception { + T6 r = JSONValue.parse(s, T6.class); + assertEquals(1, r.data.size()); + } + + String MultiTyepJson = + "{\"name\":\"B\",\"age\":120,\"cost\":12000,\"flag\":3,\"valid\":true,\"f\":1.2,\"d\":1.5,\"l\":12345678912345}"; + + public static class T5 { + public Map data; + } + + public static class T6 { + public TreeMap data; + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestSerPrimArrays.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestSerPrimArrays.java index 5c3c67b..eb9ccd0 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestSerPrimArrays.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestSerPrimArrays.java @@ -4,43 +4,39 @@ import java.text.SimpleDateFormat; import java.util.Date; - import net.minidev.json.JSONValue; - import org.junit.jupiter.api.Test; public class TestSerPrimArrays { - SimpleDateFormat sdf; - - String testDateString; - Date testDate; - - public TestSerPrimArrays() { - try { - sdf = new SimpleDateFormat("dd/MM/yyyy"); - testDateString = "12/01/2010"; - testDate = sdf.parse(testDateString); - } catch (Exception e) { - } - - } - - @Test - public void testDate() throws Exception { - String s = "'" + testDateString + "'"; - Date dt = JSONValue.parse(s, Date.class); - assertEquals(dt, this.testDate); - } - - @Test - public void testDtObj() throws Exception { - String s = "{date:'" + testDateString + "'}"; - ADate dt = JSONValue.parse(s, ADate.class); - assertEquals(dt.date, this.testDate); - } - - public static class ADate { - public Date date; - } - + SimpleDateFormat sdf; + + String testDateString; + Date testDate; + + public TestSerPrimArrays() { + try { + sdf = new SimpleDateFormat("dd/MM/yyyy"); + testDateString = "12/01/2010"; + testDate = sdf.parse(testDateString); + } catch (Exception e) { + } + } + + @Test + public void testDate() throws Exception { + String s = "'" + testDateString + "'"; + Date dt = JSONValue.parse(s, Date.class); + assertEquals(dt, this.testDate); + } + + @Test + public void testDtObj() throws Exception { + String s = "{date:'" + testDateString + "'}"; + ADate dt = JSONValue.parse(s, ADate.class); + assertEquals(dt.date, this.testDate); + } + + public static class ADate { + public Date date; + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestUUID.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestUUID.java index 62b4e14..1b04308 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestUUID.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestUUID.java @@ -1,62 +1,67 @@ package net.minidev.json.testMapping; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; +import java.util.UUID; import net.minidev.json.JSONObject; import net.minidev.json.JSONStyle; import net.minidev.json.JSONValue; import net.minidev.json.parser.ParseException; import net.minidev.json.reader.JsonWriterI; import net.minidev.json.writer.JsonReaderI; +import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +public class TestUUID { + @Test + void testUUID() throws ParseException { + JSONObject obj = new JSONObject(); + UUID uuid = new UUID(123, 456); + JSONValue.registerWriter( + UUID.class, + new JsonWriterI() { + @Override + public void writeJSONString(UUID value, Appendable out, JSONStyle compression) + throws IOException { + out.append(value.toString()); + } + }); -import java.io.IOException; -import java.util.UUID; + JSONValue.registerReader( + UUIDHolder.class, + new JsonReaderI(JSONValue.defaultReader) { + @Override + public void setValue(Object current, String key, Object value) + throws ParseException, IOException { + if ("v".equals(key)) { + ((UUIDHolder) current).setV(UUID.fromString((String) value)); + return; + } + super.setValue(current, key, value); + } -import org.junit.jupiter.api.Test; + @Override + public Object createObject() { + return new UUIDHolder(); + } + }); -public class TestUUID { - @Test - void testUUID() throws ParseException { - JSONObject obj = new JSONObject(); - UUID uuid = new UUID(123, 456); - JSONValue.registerWriter(UUID.class, new JsonWriterI() { - @Override - public void writeJSONString(UUID value, Appendable out, JSONStyle compression) throws IOException { - out.append(value.toString()); - } - }); - - JSONValue.registerReader(UUIDHolder.class, new JsonReaderI(JSONValue.defaultReader) { - @Override - public void setValue(Object current, String key, Object value) throws ParseException, IOException { - if ("v".equals(key)) { - ((UUIDHolder)current).setV(UUID.fromString((String)value)); - return; - } - super.setValue(current, key, value); - } - @Override - public Object createObject() { - return new UUIDHolder(); - } - }); - - obj.put("v", uuid); - String asText = obj.toJSONString(); - assertEquals("{\"v\":00000000-0000-007b-0000-0000000001c8}", asText); - UUIDHolder rebuild = JSONValue.parseWithException(asText, UUIDHolder.class); - assertEquals(uuid, rebuild.getV()); - } - - public static class UUIDHolder { - private UUID v; - - public UUID getV() { - return v; - } - - public void setV(UUID uuid) { - this.v = uuid; - } - } + obj.put("v", uuid); + String asText = obj.toJSONString(); + assertEquals("{\"v\":00000000-0000-007b-0000-0000000001c8}", asText); + UUIDHolder rebuild = JSONValue.parseWithException(asText, UUIDHolder.class); + assertEquals(uuid, rebuild.getV()); + } + + public static class UUIDHolder { + private UUID v; + + public UUID getV() { + return v; + } + + public void setV(UUID uuid) { + this.v = uuid; + } + } } diff --git a/json-smart/src/test/java/net/minidev/json/testMapping/TestUpdater.java b/json-smart/src/test/java/net/minidev/json/testMapping/TestUpdater.java index 3f279f0..b8dbba1 100644 --- a/json-smart/src/test/java/net/minidev/json/testMapping/TestUpdater.java +++ b/json-smart/src/test/java/net/minidev/json/testMapping/TestUpdater.java @@ -1,64 +1,62 @@ package net.minidev.json.testMapping; +import static org.junit.jupiter.api.Assertions.assertEquals; + import net.minidev.json.JSONValue; -import net.minidev.json.testMapping.TestMapPublic.T123; import net.minidev.json.testMapping.TestMapPublic.T1; +import net.minidev.json.testMapping.TestMapPublic.T123; import net.minidev.json.testMapping.TestMapPublic.T2; import net.minidev.json.testMapping.TestMapPublic.T3; - -import static org.junit.jupiter.api.Assertions.assertEquals; - import org.junit.jupiter.api.Test; public class TestUpdater { - @Test - public void testUpdate1() throws Exception { - T3 t3 = new T3(); - t3.age = 20; - t3.f = 1.4f; - t3.l = 120000L; - - String s = "{\"name\":\"text\"}"; - T3 t3_1 = JSONValue.parse(s, t3); - assertEquals(t3, t3_1); - assertEquals("text", t3.name); - assertEquals((Long) 120000L, t3.l); - } - - @Test - public void testUpdateExistingBeans() throws Exception { - T123 t123 = new T123(); - T1 t1 = new T1(); - T2 t2 = new T2(); - T3 t3 = new T3(); - t123.t1 = t1; - t123.t2 = t2; - t123.t3 = t3; - - String s = "{\"t2\":{\"name\":\"valueT2\"},\"t3\":{\"name\":\"valueT3\"},}"; - T123 res = JSONValue.parse(s, t123); - assertEquals(res, t123); - assertEquals(res.t2, t2); - assertEquals(res.t2.name, "valueT2"); - assertEquals(res.t3.name, "valueT3"); - } - - @Test - public void testUpdateNullBean() throws Exception { - T123 t123 = new T123(); - T1 t1 = new T1(); - T2 t2 = null; - T3 t3 = null; - t123.t1 = t1; - t123.t2 = t2; - t123.t3 = t3; - - String s = "{\"t2\":{\"name\":\"valueT2\"},\"t3\":{\"name\":\"valueT3\"},}"; - T123 res = JSONValue.parse(s, t123); - assertEquals(res, t123); - assertEquals(res.t2.name, "valueT2"); - assertEquals(res.t3.name, "valueT3"); - } - + @Test + public void testUpdate1() throws Exception { + T3 t3 = new T3(); + t3.age = 20; + t3.f = 1.4f; + t3.l = 120000L; + + String s = "{\"name\":\"text\"}"; + T3 t3_1 = JSONValue.parse(s, t3); + assertEquals(t3, t3_1); + assertEquals("text", t3.name); + assertEquals((Long) 120000L, t3.l); + } + + @Test + public void testUpdateExistingBeans() throws Exception { + T123 t123 = new T123(); + T1 t1 = new T1(); + T2 t2 = new T2(); + T3 t3 = new T3(); + t123.t1 = t1; + t123.t2 = t2; + t123.t3 = t3; + + String s = "{\"t2\":{\"name\":\"valueT2\"},\"t3\":{\"name\":\"valueT3\"},}"; + T123 res = JSONValue.parse(s, t123); + assertEquals(res, t123); + assertEquals(res.t2, t2); + assertEquals(res.t2.name, "valueT2"); + assertEquals(res.t3.name, "valueT3"); + } + + @Test + public void testUpdateNullBean() throws Exception { + T123 t123 = new T123(); + T1 t1 = new T1(); + T2 t2 = null; + T3 t3 = null; + t123.t1 = t1; + t123.t2 = t2; + t123.t3 = t3; + + String s = "{\"t2\":{\"name\":\"valueT2\"},\"t3\":{\"name\":\"valueT3\"},}"; + T123 res = JSONValue.parse(s, t123); + assertEquals(res, t123); + assertEquals(res.t2.name, "valueT2"); + assertEquals(res.t3.name, "valueT3"); + } }