I am using Jackson version 2.4.3 for converting my complex Java object into a String object, so below is what I'm getting in output. The output is like below (Fyi - I just printed some part of the output)
"{\"FirstName\":\"John \",\"LastName\":cena,\"salary\":7500,\"skills\":[\"java\",\"python\"]}";
Here is my code (PaymentTnx is a complex Java object)
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
String lpTransactionJSON = mapper.writeValueAsString(paymentTxn);
I don't want to see \ slashes in my JSON string. What do I need to do to get a string like below:
"{"FirstName":"John ","LastName":cena,"salary":7500,"skills":["java","python"]}";
String test = "{\"FirstName\":\"John \",\"LastName\":cena,\"salary\":7500,\"skills\":[\"java\",\"python\"]}";
System.out.println(StringEscapeUtils.unescapeJava(test));
This might help you.
I have not tried Jackson. I just have similar situation.
I used org.apache.commons.text.StringEscapeUtils.unescapeJson but it's not working for malformed JSON format like {\"name\": \"john\"}
So, I used this class. Perfectly working fine.
https://gist.githubusercontent.com/jjfiv/2ac5c081e088779f49aa/raw/8bda15d27c73047621a94359492a5a9433f497b2/JSONUtil.java
// BSD License (http://lemurproject.org/galago-license)
package org.lemurproject.galago.utility.json;
public class JSONUtil {
public static String escape(String input) {
StringBuilder output = new StringBuilder();
for(int i=0; i<input.length(); i++) {
char ch = input.charAt(i);
int chx = (int) ch;
// let's not put any nulls in our strings
assert(chx != 0);
if(ch == '\n') {
output.append("\\n");
} else if(ch == '\t') {
output.append("\\t");
} else if(ch == '\r') {
output.append("\\r");
} else if(ch == '\\') {
output.append("\\\\");
} else if(ch == '"') {
output.append("\\\"");
} else if(ch == '\b') {
output.append("\\b");
} else if(ch == '\f') {
output.append("\\f");
} else if(chx >= 0x10000) {
assert false : "Java stores as u16, so it should never give us a character that's bigger than 2 bytes. It literally can't.";
} else if(chx > 127) {
output.append(String.format("\\u%04x", chx));
} else {
output.append(ch);
}
}
return output.toString();
}
public static String unescape(String input) {
StringBuilder builder = new StringBuilder();
int i = 0;
while (i < input.length()) {
char delimiter = input.charAt(i); i++; // consume letter or backslash
if(delimiter == '\\' && i < input.length()) {
// consume first after backslash
char ch = input.charAt(i); i++;
if(ch == '\\' || ch == '/' || ch == '"' || ch == '\'') {
builder.append(ch);
}
else if(ch == 'n') builder.append('\n');
else if(ch == 'r') builder.append('\r');
else if(ch == 't') builder.append('\t');
else if(ch == 'b') builder.append('\b');
else if(ch == 'f') builder.append('\f');
else if(ch == 'u') {
StringBuilder hex = new StringBuilder();
// expect 4 digits
if (i+4 > input.length()) {
throw new RuntimeException("Not enough unicode digits! ");
}
for (char x : input.substring(i, i + 4).toCharArray()) {
if(!Character.isLetterOrDigit(x)) {
throw new RuntimeException("Bad character in unicode escape.");
}
hex.append(Character.toLowerCase(x));
}
i+=4; // consume those four digits.
int code = Integer.parseInt(hex.toString(), 16);
builder.append((char) code);
} else {
throw new RuntimeException("Illegal escape sequence: \\"+ch);
}
} else { // it's not a backslash, or it's the last character.
builder.append(delimiter);
}
}
return builder.toString();
}
}
With Jackson do:
toString(paymentTxn);
with
public String toString(Object obj) {
try (StringWriter w = new StringWriter();) {
new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true).writeValue(w, obj);
return w.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
This here is not valid JSON:
"{"FirstName":"John ","LastName":cena,"salary":7500,"skills":["java","python"]}";
This here is valid JSON, specifically a single string value:
"{\"FirstName\":\"John \",\"LastName\":cena,\"salary\":7500,\"skills\":[\"java\",\"python\"]}";
Given that you're calling writeValueAsString, this is the correct behaviour. I would suggest writeValue, perhaps?
Related
I have a string "{x{y}{a{b{c}{d}}}}"
And want to print out recursively.
x
-y
-a
--b
---c
---d
This is what I have so far -
private static void printPathInChild2(String path) {
if (path.length() == 0) {
return;
}
if (path.charAt(0) == '{') {
for (int i = 0; i < path.length(); i++) {
if (path.charAt(i) == '{' && i != 0) {
String t1 = path.substring(0,i);
System.out.println(t1);
printPathInChild2(path.substring(i));
} else if (path.charAt(i) == '}') {
String t2 = path.substring(0, i+1);
System.out.println(t2);
printPathInChild2(path.substring(i+1));
}
}
}
}
Struggling with the termination logic
If you want to add '-' characters that depend on the depth of the nesting, you should pass a second argument to the recursive call, which keeps track of the prefix of '-' characters.
When you encounter a '{', you add a '-' to the prefix.
When you encounter a '}', you remove a '-' from the prefix.
When you encounter any other character, you print the prefix followed by that character.
private static void printPathInChild2(String path,String prefix) {
if (path.length() == 0) {
return;
}
if (path.charAt(0) == '{') {
printPathInChild2(path.substring(1),prefix + "-");
} else if (path.charAt(0) == '}') {
printPathInChild2(path.substring(1),prefix.substring(0,prefix.length()-1));
} else {
System.out.println (prefix.substring(1) + path.charAt(0));
printPathInChild2(path.substring(1),prefix);
}
}
When you call this method with:
printPathInChild2("{x{y}{a{b{c}{d}}}}","");
You get:
x
-y
-a
--b
---c
---d
(I see that in your expected output 'd' has 4 '-'s, but I think it's an error, since 'd' has the same nesting level as 'c', so it should have 3 '-'s).
The method can also be written as follows:
private static void printPathInChild2(String path,String prefix) {
if (path.length() == 0) {
return;
}
char c = path.charAt(0);
if (c == '{') {
prefix = prefix + '-';
} else if (c == '}') {
prefix = prefix.substring(0,prefix.length()-1);
} else {
System.out.println (prefix.substring(1) + c);
}
printPathInChild2(path.substring(1),prefix);
}
This is code for checking balance symbol.
However, when I try to fit in a Tester,
It does not show the anwer correctly.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class BalanceCheck {
private static Scanner in;
public static void main(String[] args){
if(args.length > 0){
System.out.println(args[0]);
try {
in = new Scanner(new File(args[0]));
MyStack<Character> stack = new MyStack<>();
String str;
char ch;
while(in.hasNext()){
str = in.next();
for(int i = 0; i < str.length(); ++i){
ch = str.charAt(i);
if(ch == '(' || ch == '[' || ch == '{' ||
(ch == '/' && i < str.length() - 1 && str.charAt(i+1) == '*')){
stack.push(ch);
}
else if(ch == ')'){
if(stack.isEmpty() || stack.pop() != ch){
System.out.println(") is mismatched");
return;
}
}
else if(ch == ']'){
if(stack.isEmpty() || stack.pop() != ch){
System.out.println("] is mismatched");
return;
}
}
else if(ch == '}'){
if(stack.isEmpty() || stack.pop() != ch){
System.out.println("} is mismatched");
return;
}
}
else if(ch == '*' && i < str.length() - 1 && str.charAt(i+1) == '/'){
if(stack.isEmpty() || stack.pop() != '/'){
System.out.println("*/ is mismatched");
return;
}
}
else if(ch == '"'){
if(stack.isEmpty() || stack.top() == '"'){
if(!stack.isEmpty())
stack.pop();
}
else{
stack.push(ch);
}
}
}
}
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
else{
System.out.println("Command line argument is not provided..");
}
}
}
For instance, if I compile this tester,
/*this tests an unbalanced [ operator*/
public class Test1 {
/* this is the main method */
public static void main(String[ ) args) {
String ghana = "hello";
int test = testing();
}
public int testing() {
/*checking this too */
/* and this */
return 1;
}
}
It should show [ is mismatched. But, it shows /* is mismatched.
Please let me know solution.
And I have to create a Tester file for this code above.
How can I code a tester for this?
Thanks,
Think about what happens with the very first line:
/*this tests an unbalanced [ operator*/
When you hit the '*/', there is a '[' on the top of the stack.
You need to track when you are inside a comment so that you can ignore everything until the end.
Whenever you have an issue like this, you need to use a debugger.
Im working on a token iterator (valid tokens, "true, false, "true", "&", "!", "(", "false", "^", "true", ")".
The code is working, my question is about return values. I often run into this problem, I have return statements, but the final return statement throws off my result by duplicating the last return statement.
I think I know for sure the error lays within my placement of { and } and while i've learned they aren't necessary, since there's so many nested if's i feel they are necessary.
This seems to be a common problem to me and others ive worked with, does anyone have an idea of how to prevent this problem from happening? Thanks!
My code outputs:
line: [ ! BAD (true ^ false) % truelybad]
next token: [!]
next token: [(]
next token: [true]
next token: [^]
next token: [false]
next token: [)]
next token: [)]
and should output
next token: [!]
next token: [(]
next token: [true]
next token: [^]
next token: [false]
next token: [)]
public class TokenIter implements Iterator<String> {
ArrayList<String> token = new ArrayList<String>();
static int count = 0;
// input line to be tokenized
private String line;
// the next Token, null if no next Token
private String nextToken;
// implement
public TokenIter(String line) {
this.line = line;
}
#Override
// implement
public boolean hasNext() {
// System.out.println(count);
return count < line.length();
}
#Override
// implement
public String next() {
while (hasNext()) {
char c = line.charAt(count);
if (c == '!' || c == '!' || c == '^' || c == '(' || c == ')') {
token.add(Character.toString(c));
count++;
nextToken = Character.toString(c);
return nextToken;
} else if (c == 't' || c == 'T') {
count++;
c = line.charAt(count);
if (c == 'r') {
count++;
c = line.charAt(count);
}
if (c == 'u') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("true");
nextToken = "true";
//count++;
return nextToken;
}
} else if (c == 'f' || c == 'F') {
count++;
c = line.charAt(count);
if (c == 'a') {
count++;
c = line.charAt(count);
}
if (c == 'l') {
count++;
c = line.charAt(count);
}
if (c == 's') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}
if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("false");
nextToken = "false";
// count++;
return nextToken;
}
} else if (c == ' ') {
count++;
} else {
count++;
}
}
return nextToken;
}
#Override
// provided, do not change
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
// provided
public static void main(String[] args) {
String line;
// you can play with other inputs on the command line
if (args.length > 0)
line = args[0];
// or do the standard test
else
line = " ! BAD (true ^ false) % truelybad";
System.out.println("line: [" + line + "]");
TokenIter tokIt = new TokenIter(line);
while (tokIt.hasNext())
System.out.println("next token: [" + tokIt.next() + "]");
}
}
Problem with your code comes only when last digit is not a token.
Reason - You are checking hasNext() which is true it goes inside your code.You are not setting nextToken for this case so it uses your lask token and display it.
I updated your code to always return a value and check if value return is from token list then display otherwise ignore it.
public class test implements Iterator<String> {
static List<String> tokenList = Arrays.asList( "true", "&", "!", "(", "false", "^", "true", ")");
ArrayList<String> token = new ArrayList<String>();
static int count = 0;
// input line to be tokenized
private String line;
// the next Token, null if no next Token
private String nextToken;
// implement
public test(String line) {
this.line = line;
}
#Override
// implement
public boolean hasNext() {
// System.out.println(count);
return count < line.length();
}
#Override
// implement
public String next() {
while (hasNext()) {
char c = line.charAt(count);
if (c == '!' || c == '!' || c == '^' || c == '(' || c == ')') {
token.add(Character.toString(c));
count++;
nextToken = Character.toString(c);
return nextToken;
} else if (c == 't' || c == 'T') {
count++;
c = line.charAt(count);
if (c == 'r') {
count++;
c = line.charAt(count);
}
if (c == 'u') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("true");
nextToken = "true";
//count++;
return nextToken;
}
} else if (c == 'f' || c == 'F') {
count++;
c = line.charAt(count);
if (c == 'a') {
count++;
c = line.charAt(count);
}
if (c == 'l') {
count++;
c = line.charAt(count);
}
if (c == 's') {
count++;
c = line.charAt(count);
}
if (c == 'e') {
count++;
c = line.charAt(count);
}
if (c == ' ' || c == '!' || c == '!' || c == '^' || c == '(' || c == ')'){
token.add("false");
nextToken = "false";
// count++;
return nextToken;
}
} else if (c == ' ') {
count++;
nextToken = null;
} else {
count++;
nextToken = null;
}
}
return nextToken;
}
#Override
// provided, do not change
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}
// provided
public static void main(String[] args) {
String line;
// you can play with other inputs on the command line
if (args.length > 0)
line = args[0];
// or do the standard test
else
line = " ! BAD (true ^ false) % truelybad ";
System.out.println("line: [" + line + "]");
test tokIt = new test(line);
while (tokIt.hasNext()) {
String s = tokIt.next();
if (s != null && tokenList.contains(s))
System.out.println("next token: [" + s + "]");
}
}
}
The underlying problem here is that your hasNext() method returns true not if there is another token in the String, but if it hasn't finished parsing the String yet.
So what happens is if you put in the String " ! ! true lotsofcrap ", then calling next() will return "!", then "!", then "true", then after that has been returned, there are no more tokens in the String, yet hasNext() still returns true.
What you might consider doing is having hasNext() parse through the string, but instead of returning the next String, return true only if it finds another token ahead of the current position. Keep in mind that in hasNext(), you do not want to directly increment count. Instead, make a local variable int something = count; at the beginning of hasNext() and use that. If you fix that, then the rest of your code SHOULD work just fine.
Maybe some one can help?
How to modify this method next() that the next token can be: 'abc' text with the quotes.
Now if the text contains quote are throwed ExpressionException Unknown operator ''' at position...
#Override
public String next() {
StringBuilder token = new StringBuilder();
if (pos >= input.length()) {
return previousToken = null;
}
char ch = input.charAt(pos);
while (Character.isWhitespace(ch) && pos < input.length()) {
ch = input.charAt(++pos);
}
if (Character.isDigit(ch)) {
while ((Character.isDigit(ch) || ch == decimalSeparator)
&& (pos < input.length())) {
token.append(input.charAt(pos++));
ch = pos == input.length() ? 0 : input.charAt(pos);
}
} else if (ch == minusSign
&& Character.isDigit(peekNextChar())
&& ("(".equals(previousToken) || ",".equals(previousToken)
|| previousToken == null || operators
.containsKey(previousToken))) {
token.append(minusSign);
pos++;
token.append(next());
} else if (Character.isLetter(ch)) {
while ((Character.isLetter(ch) || Character.isDigit(ch) || (ch == '_')) && (pos < input.length())) {
token.append(input.charAt(pos++));
ch = pos == input.length() ? 0 : input.charAt(pos);
}
} else if (ch == '(' || ch == ')' || ch == ',') {
token.append(ch);
pos++;
//FIXME
else if (ch == '\''){
pos++;
String temp = "\'"+next()+"\'";
token.append(temp);
pos++;
}
//
} else {
while (!Character.isLetter(ch) && !Character.isDigit(ch)
&& !Character.isWhitespace(ch) && ch != '('
&& ch != ')' && ch != ',' && (pos < input.length())) {
token.append(input.charAt(pos));
pos++;
ch = pos == input.length() ? 0 : input.charAt(pos);
if (ch == minusSign) {
break;
}
}
if (!operators.containsKey(token.toString())) {
throw new ExpressionException("Unknown operator '" + token
+ "' at position " + (pos - token.length() + 1));
}
}
return previousToken = token.toString();
}
eval
public Object eval() {
Stack<Object> stack = new Stack<Object>();
for (String token : getRPN()) {
mylog.pl("Reverse polish notation TOKEN : " + token + " RPN size: " + getRPN().size() );
if (operators.containsKey(token)) {
Object v1 = stack.pop();
Object v2 = stack.pop();
stack.push(operators.get(token).eval(v2, v1));
} else if (variables.containsKey(token)) {
stack.push(variables.get(token).round(mc));
} else if (functions.containsKey(token.toUpperCase())) {
Function f = functions.get(token.toUpperCase());
ArrayList<Object> p = new ArrayList<Object>(f.getNumParams());
for (int i = 0; i < f.numParams; i++) {
p.add(0, stack.pop());
}
Object fResult = f.eval(p);
stack.push(fResult);
} else if (isDate(token)) {
Long date = null;
try {
date = SU.sdf.parse(token).getTime();
} catch (ParseException e) {/* IGNORE! */
}
stack.push(new BigDecimal(date, mc));
} else {
if (BusinessStrategy.PREFIX_X.equals(Character.toString(token.charAt(0)))) {
stack.push(token);
} else {
stack.push(new BigDecimal(token, mc));
}
}
}
return stack.pop();
}
Reverse notation
private List<String> getRPN() {
if (rpn == null) {
rpn = shuntingYard(this.expression);
}
return rpn;
}
Yard
private List<String> shuntingYard(String expression) {
List<String> outputQueue = new ArrayList<String>();
Stack<String> stack = new Stack<String>();
Tokenizer tokenizer = new Tokenizer(expression);
String lastFunction = null;
while (tokenizer.hasNext()) {
String token = tokenizer.next();
if (isNumber(token)) {
outputQueue.add(token);
} else if (variables.containsKey(token)) {
outputQueue.add(token);
} else if (functions.containsKey(token.toUpperCase())) {
stack.push(token);
lastFunction = token;
} else if (Character.isLetter(token.charAt(0))) {
if ("\'".equals(Character.toString(token.charAt(0)))){
outputQueue.add(token);
} else {
stack.push(token);
}
} else if (",".equals(token)) {
while (!stack.isEmpty() && !"(".equals(stack.peek())) {
outputQueue.add(stack.pop());
}
if (stack.isEmpty()) {
throw new ExpressionException("Parse error for function '"
+ lastFunction + "'");
}
} else if (operators.containsKey(token)) {
Operator o1 = operators.get(token);
String token2 = stack.isEmpty() ? null : stack.peek();
while (operators.containsKey(token2)
&& ((o1.isLeftAssoc() && o1.getPrecedence() <= operators
.get(token2).getPrecedence()) || (o1
.getPrecedence() < operators.get(token2)
.getPrecedence()))) {
outputQueue.add(stack.pop());
token2 = stack.isEmpty() ? null : stack.peek();
}
stack.push(token);
} else if ("(".equals(token)) {
stack.push(token);
} else if (")".equals(token)) {
while (!stack.isEmpty() && !"(".equals(stack.peek())) {
outputQueue.add(stack.pop());
}
if (stack.isEmpty()) {
throw new RuntimeException("Mismatched parentheses");
}
stack.pop();
if (!stack.isEmpty()
&& functions.containsKey(stack.peek().toUpperCase())) {
outputQueue.add(stack.pop());
}
}
}
while (!stack.isEmpty()) {
String element = stack.pop();
if ("(".equals(element) || ")".equals(element)) {
throw new RuntimeException("Mismatched parentheses");
}
if (!operators.containsKey(element)) {
throw new RuntimeException("Unknown operator or function: "
+ element);
}
outputQueue.add(element);
}
return outputQueue;
}
Error
*java.util.EmptyStackException
at java.util.Stack.peek(Unknown Source)
at java.util.Stack.pop(Unknown Source)
at com.business.Expression.eval(Expression.java:1033)*
It is in eval method Object v1 = stack.pop(); line.
Thanks !
In method next you have recursive calls in two places:
after seeing a minus sign
after recognizing an apostrope
The first situation will construct tokens where a minus is followed by a digit (i.e., an unsigend number follows) - OK. (Although, not having a sign but an unary minus operator deserves some consideration.)
The second scenario means trouble. After advancing past the initial apostrophe, another next-result is expected, as if string literals would only contain one number or one identifier or a single operator. Anyway, the next() executes, let's say it returns a number: then an apostroph is added to the token, but there's no effort to check whether there is a closing apostrophe nor to skip that.
else if (ch == '\''){
token.append( '\'' );
pos++;
while( pos < input.length() &&
(ch = input.charAt(pos++)) != '\'' ){
token.append( ch );
}
token.append( '\'' );
This doesn't permit an apostrophe to be a character within the string and it does not diagnose an unterminated string. But this can be added rather easily.
Basically I've got an input string, my test string is '5 + 4' and I want to check character by character to create a list in the form [5,+,4], ie white spaces are ignored. Also, if my test string was '567+5-1' it would output [567,+,5,-,1] by concatenating the numbers together. Unfortunately, it won't let me do .add(inputChar) to my returnValue, saying symbol not found... any ideas?
import java.util.*;
public class CharacterArray {
public List<String> splitToChar(String s) {
List<String> returnValue = new LinkedList<String>();
char[] chars = s.toCharArray();
System.out.println(chars);
int currentNumber;
for (char inputChar : chars) {
if (Character.isDigit(inputChar) == true) {
currentNumber += inputChar;
} else if (inputChar == '.') {
currentNumber += inputChar;
} else if (inputChar == '+') {
returnValue.add(inputChar);
} else if (inputChar == '-') {
returnValue.add(inputChar);
} else if (inputChar == '/') {
returnValue.add(inputChar);
} else if (inputChar == '*') {
returnValue.add(inputChar);
} else if (inputChar == '(') {
returnValue.add(inputChar);
} else if (inputChar == ')') {
returnValue.add(inputChar);
} else {
System.out.println("Incorrect input symbol");
}
}
return returnValue;
}
}
import java.util.*;
public class CharacterArray {
public List<String> splitToChar(String s) {
List<String> returnValue = new LinkedList<String>();
char[] chars = s.toCharArray();
System.out.println(chars);
String currentNumber = "";
for (char inputChar : chars) {
if (Character.isDigit(inputChar) == true) {
currentNumber += inputChar;
} else if (inputChar == '.' ||
inputChar == '+' ||
inputChar == '-' ||
inputChar == '/' ||
inputChar == '*' ||
inputChar == '(' ||
inputChar == ')') {
if (currentNumber.length() > 0){
returnValue.add(currentNumber);
}
currentNumber = "";
returnValue.add(""+inputChar);
} else {
System.out.println("Incorrect input symbol");
}
}
if (currentNumber.length() > 0){
returnValue.add(currentNumber);
}
return returnValue;
}
}
By the way, your currentNumber should be a String
how about .add(String.valueOf(inputChar)) ?
You can't add a char to a List<String> perhaps what you are trying to do is like
String currentNumber = "";
for (char inputChar : chars) {
if (Character.isDigit(inputChar) || inputChar == '.') {
currentNumber += inputChar;
} else if ("+-/*()".indexOf(inputChar) >= 0) {
if (currentNumber.length() > 0) returnValue.add(currentNumber);
currentNumber = "";
returnValue.add("" + inputChar);
} else if (inputChar != ' ') {
System.out.println("Incorrect input symbol '"+inputChar+"'");
}
}
if (currentNumber.length() > 0) returnValue.add(currentNumber);
Your returnValue is a List<String> but you are trying to add a char to the list. You can fix this by converting inputChar to a String when adding it to the list by using String.valueOf(inputChar).