org.codehaus.jettison.util.StringIndenter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jettison Show documentation
Show all versions of jettison Show documentation
A StAX implementation for JSON.
/**
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
package org.codehaus.jettison.util;
/**
*
* indent json, assumes the input is not yet indented. here is an example:
* {
* "FastResponseJs":{
* "ajaxElements":{
* "AjaxMapEntry":[
* {
* "theKey":{
* "@class":"string",
* "$":"ajax1a"
* },
* "theValue":{
* "@class":"AjaxEvent",
* "ajaxSendFormNames":{
* "string":"ajax1"
* },
* "ajaxEventType":"NORMAL",
* "eventName":"onblur",
* "ajaxId":"PRLZY5QZ",
* "screenElementId":"ajax1a",
* "asynchronous":true,
* "disableValidation":true
* }
*
* },
* {
* "theKey":{
* ...
*
*
* Usage: String formatted = new StringIndenter(jsonString).result();
*
*/
public class StringIndenter {
/** chars to process */
private String json;
/** current start tag */
private int startTagIndex;
/** current end tag */
private int endTagIndex;
/** current number of indents (times to is the indent */
private int currentNumberOfIndents;
/** result */
private StringBuilder result;
/**
* get the result
* @return the result
*/
public String result() {
try {
this.indent();
} catch (RuntimeException re) {
throw new RuntimeException("Problem here: " + this, re);
}
if (this.json == null) {
return null;
}
String resultString = this.result.toString();
return resultString == null ? null : resultString.trim();
}
/**
* indent the string
*/
private void indent() {
if (this.json == null) {
return;
}
this.result = new StringBuilder();
this.startTagIndex = -1;
this.endTagIndex = -1;
this.currentNumberOfIndents = 0;
//{
// "a":{
// "b\"b":{
// "c\\":"d"
// },
// "e":"f",
// "g":[
// "h":"i"
// ]
// }
//}
while(true) {
this.startTagIndex = findStartTagIndex();
if (this.startTagIndex == -1) {
//cant find anything else... make sure everything there
if (this.endTagIndex != this.json.length()-1) {
this.result.append(this.json, this.endTagIndex+1, this.json.length());
}
break;
}
//handles first tag
if (instantIndent(this.json, this.startTagIndex)) {
this.currentNumberOfIndents++;
this.printNewlineIndent(this.startTagIndex, this.startTagIndex+1);
this.endTagIndex = this.startTagIndex;
continue;
}
//handles end of associative array with comma
if (instantUnindentTwoChars(this.json, this.startTagIndex)) {
this.currentNumberOfIndents--;
//this is on a line by itself
this.newlineIndent();
this.printNewlineIndent(this.startTagIndex, this.startTagIndex+2);
this.endTagIndex = this.startTagIndex+1;
continue;
}
//handles end of array with comma
if (instantUnindent(this.json, this.startTagIndex)) {
this.currentNumberOfIndents--;
if (onNewline()) {
this.unindent();
} else {
this.newlineIndent();
}
this.printNewlineIndent(this.startTagIndex, this.startTagIndex+1);
this.endTagIndex = this.startTagIndex;
continue;
}
//handles end of array with comma
if (instantNewline(this.json, this.startTagIndex)) {
this.printNewlineIndent(this.startTagIndex, this.startTagIndex+1);
this.endTagIndex = this.startTagIndex;
continue;
}
this.endTagIndex = findEndTagIndex();
//one thing's for sure, we are printing out this tag
this.result.append(this.json, this.startTagIndex, this.endTagIndex+1);
//go back to top to end
if (this.endTagIndex >= this.json.length()-1) {
continue;
}
char nextChar = this.json.charAt(this.endTagIndex+1);
//if next is colon, print that out too
if (nextChar == ':') {
this.result.append(':');
this.endTagIndex++;
}
//ready to loop around...
}
}
/**
* see if current pos is on newline
* @return true if on new line
*/
private boolean onNewline() {
for (int i=this.result.length()-1;i>=0;i--) {
char curChar = this.result.charAt(i);
if (curChar == '\n') {
return true;
}
if (Character.isWhitespace(curChar)) {
continue;
}
//if not whitespace, then not on own line
return false;
}
//i guess first line is new line
return true;
}
/**
* see if instant indent
* @param json
* @param index
* @return if it is an instant indent
*/
private static boolean instantIndent(String json, int index) {
char curChar = json.charAt(index);
if (curChar == '{' || curChar == '[') {
return true;
}
return false;
}
/**
* see if instant indent
* @param json
* @param index
* @return if it is an instant indent
*/
private static boolean instantNewline(String json, int index) {
char curChar = json.charAt(index);
if (curChar == ',') {
return true;
}
return false;
}
/**
* see if instant unindent
* @param json
* @param index
* @return if it is an instant unindent
*/
private static boolean instantUnindent(String json, int index) {
char curChar = json.charAt(index);
if (curChar == '}' || curChar == ']') {
return true;
}
return false;
}
/**
* see if instant indent
* @param json
* @param index
* @return if it is an instant indent
*/
private static boolean instantUnindentTwoChars(String json, int index) {
char curChar = json.charAt(index);
if (index == json.length()-1) {
return false;
}
char nextchar = json.charAt(index+1);
if (curChar == '}' && nextchar == ',') {
return true;
}
return false;
}
/**
* put a newline and indent
* @param start
* @param end
*/
private void printNewlineIndent(int start, int end) {
//lets put this tag on the queue
this.result.append(this.json, start, end);
this.newlineIndent();
}
/**
* put a newline and indent
*/
private void newlineIndent() {
this.result.append("\n").append(repeat(" ", this.currentNumberOfIndents));
}
/**
* repeat a string a certain number of times.
* @param theString
* @param times
* @return the string
*/
private static String repeat(String theString, int times) {
StringBuffer result = new StringBuffer();
//loop through, keep appending
for (int i = 0; i < times; i++) {
result.append(theString);
}
return result.toString();
}
/**
* unindent a previous indent if it is there
*/
private void unindent() {
for (int i=0;i<2;i++) {
if (this.result.charAt(this.result.length()-1) == ' ') {
this.result.deleteCharAt(this.result.length()-1);
}
}
}
/**
* after the last end tag, find the next start tag
* @return the next start tag
*/
private int findStartTagIndex() {
return findNextStartTagIndex(this.json, this.endTagIndex+1);
}
/**
* after the last start tag, find the next end start tag
* @return the next start tag
*/
private int findEndTagIndex() {
return findNextEndTagIndex(this.json, this.startTagIndex+1);
}
/**
* find the start tag from json and a start from index
* either look for a quote, {, [ or scalar. generally not whitespace
* @param json
* @param startFrom
* @return the start tag index of -1 if not found another
*/
private static int findNextStartTagIndex(String json, int startFrom) {
int length = json.length();
for (int i= startFrom; i