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

com.unboundid.util.json.JSONString Maven / Gradle / Ivy

/*
 * Copyright 2015-2017 UnboundID Corp.
 * All Rights Reserved.
 */
/*
 * Copyright (C) 2015-2017 UnboundID Corp.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (GPLv2 only)
 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see .
 */
package com.unboundid.util.json;



import com.unboundid.util.ByteStringBuffer;
import com.unboundid.util.NotMutable;
import com.unboundid.util.StaticUtils;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;



/**
 * This class provides an implementation of a JSON value that represents a
 * string of Unicode characters.  The string representation of a JSON string
 * must start and end with the double quotation mark character, and a Unicode
 * (preferably UTF-8) representation of the string between the quotes.  The
 * following special characters must be escaped:
 * 
    *
  • * The double quotation mark (Unicode character U+0022) must be escaped as * either {@code \"} or {@code \}{@code u0022}. *
  • *
  • * The backslash (Unicode character U+005C) must be escaped as either * {@code \\} or {@code \}{@code u005C}. *
  • *
  • * All ASCII control characters (Unicode characters U+0000 through U+001F) * must be escaped. They can all be escaped by prefixing the * four-hexadecimal-digit Unicode character code with {@code \}{@code u}, * like {@code \}{@code u0000} to represent the ASCII null character U+0000. * For certain characters, a more user-friendly escape sequence is also * defined: *
      *
    • * The horizontal tab character can be escaped as either {@code \t} or * {@code \}{@code u0009}. *
    • *
    • * The newline character can be escaped as either {@code \n} or * {@code \}{@code u000A}. *
    • *
    • * The formfeed character can be escaped as either {@code \f} or * {@code \}{@code u000C}. *
    • *
    • * The carriage return character can be escaped as either {@code \r} or * {@code \}{@code u000D}. *
    • *
    *
  • *
* In addition, any other character may optionally be escaped by placing the * {@code \}{@code u} prefix in front of each four-hexadecimal digit sequence in * the UTF-16 representation of that character. For example, the "LATIN SMALL * LETTER N WITH TILDE" character U+00F1 may be escaped as * {@code \}{@code u00F1}, while the "MUSICAL SYMBOL G CLEF" character U+1D11E * may be escaped as {@code \}{@code uD834}{@code \}{@code uDD1E}. And while * the forward slash character is not required to be escaped in JSON strings, it * can be escaped using {@code \/} as a more human-readable alternative to * {@code \}{@code u002F}. *

* The string provided to the {@link #JSONString(String)} constructor should not * have any escaping performed, and the string returned by the * {@link #stringValue()} method will not have any escaping performed. These * methods work with the Java string that is represented by the JSON string. *

* If this JSON string was parsed from the string representation of a JSON * object, then the value returned by the {@link #toString()} method (or * appended to the buffer provided to the {@link #toString(StringBuilder)} * method) will be the string representation used in the JSON object that was * parsed. Otherwise, this class will generate an appropriate string * representation, which will be surrounded by quotation marks and will have the * minimal required encoding applied. *

* The string returned by the {@link #toNormalizedString()} method (or appended * to the buffer provided to the {@link #toNormalizedString(StringBuilder)} * method) will be generated by converting it to lowercase, surrounding it with * quotation marks, and using the {@code \}{@code u}-style escaping for all * characters other than the following (as contained in the LDAP printable * character set defined in RFC * 4517 section 3.2, and indicated by the * {@link StaticUtils#isPrintable(char)} method): *
    *
  • All uppercase ASCII alphabetic letters (U+0041 through U+005A).
  • *
  • All lowercase ASCII alphabetic letters (U+0061 through U+007A).
  • *
  • All ASCII numeric digits (U+0030 through U+0039).
  • *
  • The ASCII space character U+0020.
  • *
  • The ASCII single quote (aka apostrophe) character U+0027.
  • *
  • The ASCII left parenthesis character U+0028.
  • *
  • The ASCII right parenthesis character U+0029.
  • *
  • The ASCII plus sign character U+002B.
  • *
  • The ASCII comma character U+002C.
  • *
  • The ASCII minus sign (aka hyphen) character U+002D.
  • *
  • The ASCII period character U+002E.
  • *
  • The ASCII forward slash character U+002F.
  • *
  • The ASCII colon character U+003A.
  • *
  • The ASCII equals sign character U+003D.
  • *
  • The ASCII question mark character U+003F.
  • *
*/ @NotMutable() @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) public final class JSONString extends JSONValue { /** * The serial version UID for this serializable class. */ private static final long serialVersionUID = -4677194657299153890L; // The JSON-formatted string representation for this JSON string. It will be // surrounded by quotation marks and any necessary escaping will have been // performed. private String jsonStringRepresentation; // The string value for this object. private final String value; /** * Creates a new JSON string. * * @param value The string to represent in this JSON value. It must not be * {@code null}. */ public JSONString(final String value) { this.value = value; jsonStringRepresentation = null; } /** * Creates a new JSON string. This method should be used for strings parsed * from the string representation of a JSON object. * * @param javaString The Java string to represent. * @param jsonString The JSON string representation to use for the Java * string. */ JSONString(final String javaString, final String jsonString) { value = javaString; jsonStringRepresentation = jsonString; } /** * Retrieves the string value for this object. This will be the interpreted * value, without the surrounding quotation marks or escaping. * * @return The string value for this object. */ public String stringValue() { return value; } /** * {@inheritDoc} */ @Override() public int hashCode() { return stringValue().hashCode(); } /** * {@inheritDoc} */ @Override() public boolean equals(final Object o) { if (o == this) { return true; } if (o instanceof JSONString) { final JSONString s = (JSONString) o; return value.equals(s.value); } return false; } /** * Indicates whether the value of this JSON string matches that of the * provided string, optionally ignoring differences in capitalization. * * @param s The JSON string to compare against this JSON string. * It must not be {@code null}. * @param ignoreCase Indicates whether to ignore differences in * capitalization. * * @return {@code true} if the value of this JSON string matches the value of * the provided string (optionally ignoring differences in * capitalization), or {@code false} if not. */ public boolean equals(final JSONString s, final boolean ignoreCase) { if (ignoreCase) { return value.equalsIgnoreCase(s.value); } else { return value.equals(s.value); } } /** * {@inheritDoc} */ @Override() public boolean equals(final JSONValue v, final boolean ignoreFieldNameCase, final boolean ignoreValueCase, final boolean ignoreArrayOrder) { return ((v instanceof JSONString) && equals((JSONString) v, ignoreValueCase)); } /** * Retrieves a string representation of this JSON string as it should appear * in a JSON object, including the surrounding quotation marks and any * appropriate escaping To obtain the string to which this value refers * without the surrounding quotation marks or escaping, use the * {@link #stringValue()} method. *

* If the object containing this string was decoded from a string, then this * method will use the same string representation as in that original object. * Otherwise, the string representation will be constructed. * * @return A string representation of this value as it should appear in a * JSON object. */ @Override() public String toString() { if (jsonStringRepresentation == null) { final StringBuilder buffer = new StringBuilder(); toString(buffer); jsonStringRepresentation = buffer.toString(); } return jsonStringRepresentation; } /** * Appends a string representation of this JSON string as it should appear * in a JSON object, including the surrounding quotation marks and any * appropriate escaping, to the provided buffer. To obtain the string to * which this value refers without the surrounding quotation marks or * escaping, use the {@link #stringValue()} method. *

* If the object containing this string was decoded from a string, then this * method will use the same string representation as in that original object. * Otherwise, the string representation will be constructed. * * @param buffer The buffer to which the information should be appended. */ @Override() public void toString(final StringBuilder buffer) { if (jsonStringRepresentation != null) { buffer.append(jsonStringRepresentation); } else { final boolean emptyBufferProvided = (buffer.length() == 0); encodeString(value, buffer); if (emptyBufferProvided) { jsonStringRepresentation = buffer.toString(); } } } /** * Retrieves a single-line representation of this JSON string as it should * appear in a JSON object, including the surrounding quotation marks and any * appropriate escaping. To obtain the string to which this value refers * without the surrounding quotation marks or escaping, use the * {@link #stringValue()} method. * * @return A single-line representation of this value as it should appear in * a JSON object. */ @Override() public String toSingleLineString() { return toString(); } /** * Appends a single-line string representation of this JSON string as it * should appear in a JSON object, including the surrounding quotation marks * and any appropriate escaping, to the provided buffer. To obtain the string * to which this value refers without the surrounding quotation marks or * escaping, use the {@link #stringValue()} method. * * @param buffer The buffer to which the information should be appended. */ @Override() public void toSingleLineString(final StringBuilder buffer) { toString(buffer); } /** * Appends a minimally-escaped JSON representation of the provided string to * the given buffer. When escaping is required, the most user-friendly form * of escaping will be used. * * @param s The string to be encoded. * @param buffer The buffer to which the encoded representation should be * appended. */ static void encodeString(final String s, final StringBuilder buffer) { buffer.append('"'); for (final char c : s.toCharArray()) { switch (c) { case '"': buffer.append("\\\""); break; case '\\': buffer.append("\\\\"); break; case '\b': // backspace buffer.append("\\b"); break; case '\f': // formfeed buffer.append("\\f"); break; case '\n': // newline buffer.append("\\n"); break; case '\r': // carriage return buffer.append("\\r"); break; case '\t': // horizontal tab buffer.append("\\t"); break; default: if (c <= '\u001F') { buffer.append("\\u"); buffer.append(String.format("%04X", (int) c)); } else { buffer.append(c); } break; } } buffer.append('"'); } /** * Appends a minimally-escaped JSON representation of the provided string to * the given buffer. When escaping is required, the most user-friendly form * of escaping will be used. * * @param s The string to be encoded. * @param buffer The buffer to which the encoded representation should be * appended. */ static void encodeString(final String s, final ByteStringBuffer buffer) { buffer.append('"'); for (final char c : s.toCharArray()) { switch (c) { case '"': buffer.append("\\\""); break; case '\\': buffer.append("\\\\"); break; case '\b': // backspace buffer.append("\\b"); break; case '\f': // formfeed buffer.append("\\f"); break; case '\n': // newline buffer.append("\\n"); break; case '\r': // carriage return buffer.append("\\r"); break; case '\t': // horizontal tab buffer.append("\\t"); break; default: if (c <= '\u001F') { buffer.append("\\u"); buffer.append(String.format("%04X", (int) c)); } else { buffer.append(c); } break; } } buffer.append('"'); } /** * Retrieves a normalized representation of this JSON string as it should * appear in a JSON object, including the surrounding quotes and any * appropriate escaping. The normalized representation will use the unescaped * ASCII representation of all of the following characters: *
    *
  • The letters a through z (ASCII character codes 0x61 through * 0x7A).
  • *
  • The digits 0 through 9 (ASCII character codes 0x30 through * 0x39).
  • *
  • The space (ASCII character code 0x20).
  • *
  • The single quote (ASCII character code 0x27).
  • *
  • The left parenthesis (ASCII character code 0x28).
  • *
  • The right parenthesis (ASCII character code 0x29).
  • *
  • The plus sign (ASCII character code 0x2B).
  • *
  • The comma (ASCII character code 0x2C).
  • *
  • The hyphen (ASCII character code 0x2D).
  • *
  • The period (ASCII character code 0x2E).
  • *
  • The forward slash (ASCII character code 0x2F).
  • *
  • The colon (ASCII character code 0x3A).
  • *
  • The equal sign (ASCII character code 0x3D).
  • *
  • The question mark (ASCII character code 0x3F).
  • *
* All characters except those listed above will be escaped using their * Unicode representation. * * @return A normalized representation of this JSON string as it should * appear in a JSON object, including */ @Override() public String toNormalizedString() { final StringBuilder buffer = new StringBuilder(); toNormalizedString(buffer); return buffer.toString(); } /** * Appends a normalized representation of this JSON string as it should * appear in a JSON object, including the surrounding quotes and any * appropriate escaping, to the provided buffer. The normalized * representation will use the unescaped ASCII representation of all of the * following characters: *
    *
  • The letters a through z (ASCII character codes 0x61 through * 0x7A).
  • *
  • The digits 0 through 9 (ASCII character codes 0x30 through * 0x39).
  • *
  • The space (ASCII character code 0x20).
  • *
  • The single quote (ASCII character code 0x27).
  • *
  • The left parenthesis (ASCII character code 0x28).
  • *
  • The right parenthesis (ASCII character code 0x29).
  • *
  • The plus sign (ASCII character code 0x2B).
  • *
  • The comma (ASCII character code 0x2C).
  • *
  • The hyphen (ASCII character code 0x2D).
  • *
  • The period (ASCII character code 0x2E).
  • *
  • The forward slash (ASCII character code 0x2F).
  • *
  • The colon (ASCII character code 0x3A).
  • *
  • The equal sign (ASCII character code 0x3D).
  • *
  • The question mark (ASCII character code 0x3F).
  • *
* All characters except those listed above will be escaped using their * Unicode representation. * * @param buffer The buffer to which the information should be appended. */ @Override() public void toNormalizedString(final StringBuilder buffer) { buffer.append('"'); for (final char c : value.toLowerCase().toCharArray()) { if (StaticUtils.isPrintable(c)) { buffer.append(c); } else { buffer.append("\\u"); buffer.append(String.format("%04X", (int) c)); } } buffer.append('"'); } /** * {@inheritDoc} */ @Override() public void appendToJSONBuffer(final JSONBuffer buffer) { buffer.appendString(value); } /** * {@inheritDoc} */ @Override() public void appendToJSONBuffer(final String fieldName, final JSONBuffer buffer) { buffer.appendString(fieldName, value); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy