In Java I have a json string and I want to remove the extra white spaces from it. I don't want to remove the space from the character in keys and values.
Actual JSON string
{ "Error" : "Invalid HTTP Method" , "ErrorCode" : "405" , "ErrorDesc" : "Method Not Allowed" }
Required JSON
{"Error":"Invalid HTTP Method","ErrorCode":"405","ErrorDesc":"Method Not Allowed"}
An even simpler an safer solution would be to use the Gson library (Only a few lines needed):
public static String simplify(String json) {
Gson gson = new GsonBuilder().create();
JsonElement el = JsonParser.parseString(json);
return gson.toJson(el);
}
and you can even reverse the entire process (adding spaces) with Gson's pretty printing option:
public static String beautify(String json) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonElement el = JsonParser.parseString(json);
return gson.toJson(el);
}
Hope this will help you
You get the latest version from here:
Gson Maven Repository
I´d go with something like this:
public static void main(String[] args) {
String json = "{ \"Error\": \"Inv\\\"alid HTTP Method\", \"ErrorCode\":\"405\",\"ErrorDesc\":\"Method Not Allowed\"}";
System.out.println(removeWhitespaces(json));
}
public static String removeWhitespaces(String json) {
boolean quoted = false;
boolean escaped = false;
String out = "";
for(Character c : json.toCharArray()) {
if(escaped) {
out += c;
escaped = false;
continue;
}
if(c == '"') {
quoted = !quoted;
} else if(c == '\\') {
escaped = true;
}
if(c == ' ' &! quoted) {
continue;
}
out += c;
}
return out;
}
Testrun returns
{"Error":"Invalid HTTP Method","ErrorCode":"405","ErrorDesc":"Method Not Allowed"}
What #Fabian Z said would probably work, but could be optimized (You don't need to convert the entire String to a char array first to iterate it and you should also use a StringBuilder):
public static String removeWhitespaces(String json) {
boolean quoted = false;
StringBuilder builder = new StringBuilder();
int len = json.length();
for (int i = 0; i < len; i++) {
char c = json.charAt(i);
if (c == '\"')
quoted = !quoted;
if (quoted || !Character.isWhitespace(c))
builder.append(c);
}
return builder.toString();
}
Also when using
Character.isWhitespace(c)
it will also remove line breaks
Don't forget about escaped quotes \"!
static String minimize(String input){
StringBuffer strBuffer = new StringBuffer();
boolean qouteOpened = false;
boolean wasEscaped = false;
for(int i=0; i<input.length(); i++){
char c = input.charAt(i);
if (c == '\\') {
wasEscaped = true;
}
if(c == '"') {
qouteOpened = wasEscaped ? qouteOpened : !qouteOpened;
}
if(!qouteOpened && (c == ' ')){
continue;
}
if (c != '\\') {
wasEscaped = false;
}
strBuffer.append(c);
}
return strBuffer.toString();
}
If you are using a JsonWriter to create that Json code, you could do
jsonWriter.setIndent("");
to remove all whitespaces in json code (Tested with Gson's Json Writer)
Ok this is probably my final answer to this post:
public static CharSequence removeWhitespaces(CharSequence json) {
int len = json.length();
StringBuilder builder = new StringBuilder(len);
boolean escaped = false, quoted = false;
for (int i = 0; i < len; i++) {
char c = json.charAt(i);
if (c == '\"') {
if (!escaped) quoted = !quoted;
else escaped = false;
} else if (quoted && c == '\\') {
escaped = true;
}
if (quoted || c != ' ') {
builder.append(c);
}
}
return builder;
}
Or if you want to assure that you got rid of all whitespace characters then use:
public static CharSequence removeWhitespaces(CharSequence json) {
int len = json.length();
StringBuilder builder = new StringBuilder(len);
boolean escaped = false, quoted = false;
for (int i = 0; i < len; i++) {
char c = json.charAt(i);
if (c == '\"') {
if (!escaped) quoted = !quoted;
else escaped = false;
} else if (quoted && c == '\\') {
escaped = true;
}
if (quoted || !Character.isWhitespace(c)) {
builder.append(c);
}
}
return builder;
}
This method is way more efficient than to first convert the string into a Json structure and back to a string, because that would be way to time consuming.
Telling the StringBuilder in advance which start capacity it should have also speeds up the process by a lot, if you have a long input String.
(Capacity is not equals to length, meaning that even if you tell the StringBuilder eg. it should have a capacity of 100 it will still only have a length of the text you put into it)
And since StringBuilder implements CharSequence you can directly return the entire StringBuilder instead of converting it back to a String. But if you need a String and not a CharSequence, just call builder.toString(); at the end of this method and set the return type to String.
Related
The input is a (good) example((eo)--)e). I have used an iterative way.
I tried with the following code:
public String scartaParentesi(String s)
{
ups = s.replaceAll("\\([^()]*\\)", "");
return ups;
}
The output of this code is a example(--)e).
The expected output is a examplee).
Based on description and comments, you can do:
String str = "a (good) example((eo)--)e";
StringBuilder stringBuilder = new StringBuilder();
int openedParenthesesCount = 0;
for (char c : str.toCharArray()) {
if (c == '(') {
openedParenthesesCount++;
} else if (c == ')') {
openedParenthesesCount--;
} else if (openedParenthesesCount == 0) {
stringBuilder.append(c);
}
}
System.out.println(stringBuilder);
Output:
a examplee
Assumption - number of '(' equals to number of ')'.
A more robust solution without any assumptions of the number of opening and closing braces:
String text = "a (good) example((eo)--)e)";
StringBuilder outText = new StringBuilder();
Deque<Character> stack = new ArrayDeque<Character>();
int i=0;
while (i<text.length()) {
if (text.charAt(i) == '(') {
stack.addFirst(text.charAt(i));
i++;
}
while (!stack.isEmpty()) {
if (text.charAt(i) != ')') {
stack.addFirst(text.charAt(i));
i++;
} else {
if (stack.removeFirst() == '(') {
i++;
}
}
}
outText.append(text.charAt(i));
i++;
}
Output:
before: a (good) example((eo)--)e)
after: a examplee)
You can also use your original String replaceAll method by putting it on a loop, replacing the same pattern on the last updated string. The break condition of the loop will be checking if 2 consecutive iterations output the same string, i.e. no pattern to replace:
String prev = text.replaceAll("\\([^()]*\\)", "");
while (!text.equals(prev)) {
prev = text;
text = text.replaceAll("\\([^()]*\\)", "");
}
System.out.println("after2: " + text);
Example (replacing 'text' with '...'):
Before:
text(text)text
After:
...(text)...
In this case it is easier to find what you want to keep, and replace the rest.
E.g. like this:
static String abbreviate(String input, String openTag, String closeTag) {
String regex = Pattern.quote(openTag) + ".*?" + Pattern.quote(closeTag);
StringBuilder buf = new StringBuilder();
int start = 0;
for (Matcher m = Pattern.compile(regex).matcher(input); m.find(); start = m.end()) {
if (start < m.start())
buf.append("...");
buf.append(m.group());
}
if (start < input.length())
buf.append("...");
return buf.toString();
}
Test
System.out.println(abbreviate("text(text)text(text)text", "(", ")"));
System.out.println(abbreviate("text$text$text$text$text$text", "$", "$"));
System.out.println(abbreviate("text(text)text", ")", "("));
Output
...(text)...(text)...
...$text$...$text$...
...
You need to iterate over the characters and only append those that are between the two specified characters. This can be done as follows:
private String splitStr(String str, char first, char second) {
StringBuilder sb = new StringBuilder();
if(str.isEmpty() || str.indexOf(first) < 0 || str.indexOf(second) < 0)
return sb.toString();
char[] chars = str.toCharArray();
boolean append = false;
for(char c : chars) {
if(c == first) {
sb.append(c);
append = true;
}else if(c == second) {
sb.append(c);
append = false;
}else if(append)
sb.append(c);
}
return sb.toString();
}
Some sample cases are:
"text(text)text(text)text(text)text" => "(text)(text)(text)"
"text(text)text" => "(text)"
String s = "text(text)text";
String newString = s.replace("text", "...");
System.out.println(newString); //returns ...(...)...
Note that "(text)" still contains "text", the braces around it will not stop it from being replaced.
You need to assign the result to a new String to use it. Strings are immutable
I am creating a method that creates a file that contains the Strings from another file that can have anything( ints, doubles... ). I am using another method that returns true if the input its a String.
public static void buscarFichero(String ftx){
File f = new File(ftx);
Scanner s = null;
PrintWriter p = null;
try{
s = new Scanner(f).useLocale(Locale.US);
p = new PrintWriter(ftx + "_nuevo");
while(s.hasNextLine()){
String aux = s.nextLine();
if(esString(aux) == true){
String b = aux.trim();
p.println(b);
}
}
}catch(FileNotFoundException e){}
finally{
if(s != null){ s.close(); }
if(p != null){ p.close(); }
}
}
public static boolean esString(String x){
if(x.equals(x.toString())){ return true;}
else{ return false; }
}
I know I am using and auxiliar that it is always making the nextLine into a String, but I have not the knowledge to fix it. I want to get rid of everything that it is not a String
Everything you read from a file is going to technically be a String. I believe that what you are trying to accomplish is to distinguish whether or not a particular String contains only letters. If this is true then what you need to do is compare the character codes. In this example I check if the character is not a character from a-z or A-Z. If so, then it is not a word.
private static boolean isWord(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
return false;
}
}
return true;
}
I'm dealing with logical expressions in strings. So far I have worked on the following method.
public static String modify(String expression)
{
String temp = expression;
String validated = "";
for(int idx=0; idx<temp.length(); idx++)
{
if(idx!=temp.length()-1)
{
if((Character.isAlphabetic(temp.charAt(idx))) && (Character.isAlphabetic(temp.charAt(idx+1))))
{
validated+=temp.substring(idx,idx+1);
validated+="*";
}
else
validated+=temp.substring(idx,idx+1);
}
else
validated+=temp.substring(idx);
}
return validated;
}
The following are examples of supposed input/output
input: AB+BC+ABC / output: (A*B)+(B*C)+(A*B*C)
input: (A+B)+ABC / output: (A+B)+(A*B*C)
input: (A+B)*(B+C)*(AB) / output: (A+B)*(B+C)*(A*B)
One way you can do it is simply keeping track of brackets with a boolean semaphore
public static String modify(String expression)
{
String temp = expression;
StringBuilder validated = new StringBuilder();
boolean inBrackets=false;
for(int idx=0; idx<temp.length()-1; idx++)
{
if((Character.isLetter(temp.charAt(idx))) && (Character.isLetter(temp.charAt(idx+1))))
{
if(!inBrackets){
inBrackets = true;
validated.append("(");
}
validated.append(temp.substring(idx,idx+1));
validated.append("*");
}
else{
validated.append(temp.substring(idx,idx+1));
if(inBrackets){
validated.append(")");
inBrackets=false;
}
}
}
validated.append(temp.substring(temp.length()-1));
if(inBrackets){
validated.append(")");
inBrackets=false;
}
return validated.toString();
}
Also never use string concatenation instead use StringBuilder or its predecessor StringBuffer in case you are seeking thread safe solution.
Here is what I would do, using StringBuilder and a split:
public static String modify(String expression)
{
StringBuilder finalString = new StringBuilder();
String[] subExpressions = expression.split("\\+");
List<String> formattedSubExpressions = new ArrayList<String>();
for (String subExpression : subExpressions) {
if (subExpression.length() > 1) {
StringBuilder formattedSubExpression = new StringBuilder();
formattedSubExpression.append("(");
for (int i=0; i<subExpression.length(); i++) {
formattedSubExpression.append(subExpression.charAt(i));
if (i != subExpression.length() -1 ) {
formattedSubExpression.append("*");
}
}
formattedSubExpression.append(")");
formattedSubExpressions.add(formattedSubExpression.toString());
} else {
formattedSubExpressions.add(subExpression);
}
}
for (String subExpression : formattedSubExpressions) {
finalString.append(subExpression);
finalString.append("+");
}
if (finalString.charAt(finalString.length() - 1) == '+') {
finalString.deleteCharAt(finalString.length() - 1);
}
return finalString.toString();
}
It gives the following sample input/output:
AB+CD: (A*B)+(C*D)
AB+CD+EF: (A*B)+(C*D)+(E*F)
AB+CD+EFGH: (A*B)+(C*D)+(E*F*G*H)
I based this answer on the idea that what you want to do is group repeating alpha characters between parentheses and put an asterisks between them regardless of the operation (add, subtract, divide, etc) being performed between the groups.
private static final Pattern p = Pattern.compile("[a-zA-Z]{2,}");
public String parse(String s){
if(s == null || "".equals(s)) {
return s;
}
char[] chars = s.toCharArray();
StringBuilder sb = new StringBuilder(100);
Matcher m = p.matcher(s);
int i = 0;
while(i<chars.length && m.find()){
int startIdx = m.start();
int endIdx = m.end();
// Need to get the leading part of the string before this matching region
while(i < startIdx){
sb.append(chars[i]);
i++;
}
sb.append('('); // Start getting the match region
while(i < endIdx){
sb.append(chars[i]);
if(i < endIdx - 1){
sb.append('*');
}
i++;
}
sb.append(')'); // end the match region
}
// If there is a region beyond the last match, append it
if(i < chars.length -1){
for(; i < chars.length; i++){
sb.append(chars[i]);
}
}
return sb.toString();
}
How can I convert a string in the form eyesOfTheTiger to one that reads eyes-of-the-tiger?
Just travel through the string and take different action if the character is uppercase.
public class Test {
private static String upperCaseToDash(String input) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (Character.isUpperCase(c))
sb.append('-').append(Character.toLowerCase(c));
else
sb.append(c);
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(upperCaseToDash("eyesOfTheTiger"));
}
}
Before you start implementing this function yourself via substrings, regex, etc, consider using Google Guava. Class com.google.common.base.CaseFormat solves exactly what you intend to do.
In your case you need the LOWER_CAMEL and LOWER_HYPHEN class constants and the to(CaseFormat format, String s) method.
IMO, it's always better to use a mature and well-tested library than to implement everything yourself.
You can split() the String using a regex , like "(?<!(^|[A-Z0-9]))(?=[A-Z0-9])|(?<!^)(?=[A-Z][a-z])" and then append - at the end of each split .
public String camelCaseToDashSeparated(String initialString) {
if(initialString==null || initialString.length()<1)
return initialString;
StringBuilder str = new StringBuilder();
for (String w : "eyesOfTheTiger".split("(?<!(^|[A-Z0-9]))(?=[A-Z0-9])|(?<!^)(?=[A-Z][a-z])")) {
str.append(w.toLowerCase()+"-");
}
return str.substring(0, str.length()-1);
}
Another way would be :
Travel through the String , char by char , keep adding the characters to the StringBuilder. Once you find a char in uppercase , append - to the StringBuilder with the lowercase of the char.
public static String camelCaseToDashSeparated2 (String initialString) {
StringBuffer buff = new StringBuffer();
for(int x = 0; x < initialString.length(); x++) {
char c = initialString.charAt(x);
if(Character.isUpperCase(c)) {
buff.append("-").append(Character.toLowerCase(c));
}
else {
buff.append(c);
}
}
return buff.toString();
}
Quick and dirty solution could be something like this:
(you should decide what to do with spaces, dashes, full stops,
languages other than English etc.)
public static String toDashed(String value) {
if (null == value)
return null;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < value.length(); ++i) {
char ch = value.charAt(i);
if ((ch >= 'A') && (ch <= 'Z') && (i > 0)) {
sb.append('-');
sb.append(Character.toLowerCase(ch));
}
else
sb.append(ch);
}
return sb.toString();
}