Dynamic parameter replace single quot while replacing - java

I am replacing dynamic parameter using dynamic values of any string.
I have used below code :
public static String setDynamicParameter(String text,Object[] values){
MessageFormat messageFormat = new MessageFormat(text);
return messageFormat.format(values);
}
public static void main(String [] args) {
String text = "Test message 'test'";
System.out.println(setDynamicParameter(text, null));
}
In the above code I am not using any dynamic parameter for test purpose.
OUTPUT : Test message test
What I am facing problem : It replace the single quot.
why it replaced single quot?

This is from the MessageFormat documentation:
Within a String, a pair of single quotes can be used to quote any arbitrary characters except single quotes. For example, pattern string "'{0}'" represents string "{0}", not a FormatElement. A single quote itself must be represented by doubled single quotes '' throughout a String.

Related

When parse the string to JsonElement, how to avoid auto read escape character?

I have a simple json str like below
{
"foo":"\uv"
}
I want to use gson to parse this str to jsonElement.
eg.
String input = "{\"foo\":\"\\uv\"}";
JsonElement element = JsonParser.parseString(input);
But gson throw the com.google.gson.JsonSyntaxException, java.lang.NumberFormatException: \uv
It seems like when JsonReader meet the '\', it will automaticly treat it as a escape character.So, What can I do to make gson treat it as plain text instead of escape character?
What you want to do should not be possible. Forcing gson to accept \ as plain text would be forcing it to not follow json conventions.
Also your json is not valid, correct one would be:
{
"foo":"\\uv"
}
Check gson adding backslash in string, it has good explanation. Using your code as example:
public class Temp {
public static void main(String[] args) {
String input = "{\"foo\":\"\\\\uv\"}";
JsonElement element = JsonParser.parseString(input);
System.out.println("foo value - " + element.getAsJsonObject().getAsJsonPrimitive("foo").getAsString());
}
}
This prints - foo value - \uv, which should be exactly the value your consumers need.

Spring Boot Spel expression concatenate variables and convert them to lower case?

Consider this method signature that I have
#Cacheable(
key="#name+'::'+#age+'::'+#country"
)
public User validate(String name, String age, String country) {
...
}
Notice the key that I have. Currently I am able to concatenate the name, age and country variables. But on top of concatenating them, I also want to convert the entire expression into a lowercase value.
For example if someone called this method like so: validate("John","24","USA"),
then I want my key to be resolved as: john::24::usa. Notice all the uppercase letters have become lowercase.
TLDR; how to write a spel expression which concatenates multiple variables and converts the entire result into lowercase?
Expression exp = new SpelExpressionParser()
.parseExpression("(#foo + '::' + #bar).toLowerCase()");
StandardEvaluationContext ctx = new StandardEvaluationContext();
ctx.setVariable("foo", "XXX");
ctx.setVariable("bar", "YYY");
System.out.println(exp.getValue(ctx));
xxx::yyy

how to remove the slashes from json key while converting object into string

I'm trying to convert JSON object into string by doing the below
JSONObject object = new JSONObject();
object.put("video", data);
array1.add( object.toString().replace("\\\\"," "));
Actual result
["{\"photos\":\"/contests/1/images/1.png\"}",
{\"photos\":\"/contests/1/images/2.png\"}"]
Expected result
["{"photos":"/contests/1/images/1.png\"}","
{"photos":"/contests/1/images/2.png\"}"]
not able to remove the slashes from key
Use replaceAll instead of replace
replaceAll("\\\\", "")
When you want to replace all the occurences with .replace, the first parameter must be a regex, if you supply a string, only the first occurrence will be replaced, that's why your replace wouldn't work.
Please use:
.replace("/\\/g","")
Alternatively, replaceAll can be used as #Code_Mono suggested
The Code_Mode mentioned is correct one.
Because String is immutable. Make sure that you put it right place.
You can refer code bellow for more detail:
public static void main(String[] args) {
String json = "[\"{\\\"photos\\\":\\\"/contests/1/images/1.png\\\"}\", {\\\"photos\\\":\\\"/contests/1/images/2.png\\\"}\"]";
json.replaceAll("\\\\","");
System.out.println(json);
String jsonReplace = json.replaceAll("\\\\","");
System.out.println(jsonReplace);
}
Output value:
["{\"photos\":\"/contests/1/images/1.png\"}", {\"photos\":\"/contests/1/images/2.png\"}"]
["{"photos":"/contests/1/images/1.png"}", {"photos":"/contests/1/images/2.png"}"]

Split JSON objects in array string using regex

I have a String in the following format:
[{"HostName":"taskmanager1","Rack":"/default-rack","State":"RUNNING","NodeId":"taskmanager1:45454","NodeHTTPAddress":"taskmanager1:8042","LastHealthUpdate":1519568501615,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},{"HostName":"datanode2","Rack":"/default-rack","State":"RUNNING","NodeId":"datanode2:45454","NodeHTTPAddress":"datanode2:8042","LastHealthUpdate":1519260876106,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},{"HostName":"taskmanager3","Rack":"/default-rack","State":"RUNNING","NodeId":"taskmanager3:45454","NodeHTTPAddress":"taskmanager3:8042","LastHealthUpdate":1519568502251,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},{"HostName":"datanode3","Rack":"/default-rack","State":"RUNNING","NodeId":"datanode3:45454","NodeHTTPAddress":"datanode3:8042","LastHealthUpdate":1519260871527,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},{"HostName":"taskmanager2","Rack":"/default-rack","State":"RUNNING","NodeId":"taskmanager2:45454","NodeHTTPAddress":"taskmanager2:8042","LastHealthUpdate":1519568502259,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},{"HostName":"datanode1","Rack":"/default-rack","State":"RUNNING","NodeId":"datanode1:45454","NodeHTTPAddress":"datanode1:8042","LastHealthUpdate":1519260875647,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024}]
I want to split it into multiple (here 6) JSON format, but my pattern cannot split that as desired.
I want something like this:
{"HostName":"taskmanager1","Rack":"/default-rack","State":"RUNNING","NodeId":"taskmanager1:45454","NodeHTTPAddress":"taskmanager1:8042","LastHealthUpdate":1519568501615,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},
{"HostName":"datanode2","Rack":"/default-rack","State":"RUNNING","NodeId":"datanode2:45454","NodeHTTPAddress":"datanode2:8042","LastHealthUpdate":1519260876106,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},
{"HostName":"taskmanager3","Rack":"/default-rack","State":"RUNNING","NodeId":"taskmanager3:45454","NodeHTTPAddress":"taskmanager3:8042","LastHealthUpdate":1519568502251,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},
{"HostName":"datanode3","Rack":"/default-rack","State":"RUNNING","NodeId":"datanode3:45454","NodeHTTPAddress":"datanode3:8042","LastHealthUpdate":1519260871527,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024}
,{"HostName":"taskmanager2","Rack":"/default-rack","State":"RUNNING","NodeId":"taskmanager2:45454","NodeHTTPAddress":"taskmanager2:8042","LastHealthUpdate":1519568502259,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024},
{"HostName":"datanode1","Rack":"/default-rack","State":"RUNNING","NodeId":"datanode1:45454","NodeHTTPAddress":"datanode1:8042","LastHealthUpdate":1519260875647,"HealthReport":"","NodeManagerVersion":"2.8.3","NumContainers":0,"UsedMemoryMB":0,"AvailableMemoryMB":1024}
Using the code:
List<String> res = Arrays.asList(temp.replace('[', ' ').replace(']',' ').trim()).split(",");
It will be split for every , character and using the pattern split("},\\}") will remove } and { character, too.
How can I split that as desire to make Json objects?
Using the Java pattern (\\{.+}) will group whole string.
You can parse the JSON as an array and treat the contents as individual strings. Here is sample code:
import org.json.JSONArray;
public class orgJson1Main {
private static final String sample = "[{\"HostName\":\"taskmanager1\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"taskmanager1:45454\",\"NodeHTTPAddress\":\"taskmanager1:8042\",\"LastHealthUpdate\":1519568501615,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"datanode2\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"datanode2:45454\",\"NodeHTTPAddress\":\"datanode2:8042\",\"LastHealthUpdate\":1519260876106,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"taskmanager3\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"taskmanager3:45454\",\"NodeHTTPAddress\":\"taskmanager3:8042\",\"LastHealthUpdate\":1519568502251,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"datanode3\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"datanode3:45454\",\"NodeHTTPAddress\":\"datanode3:8042\",\"LastHealthUpdate\":1519260871527,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"taskmanager2\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"taskmanager2:45454\",\"NodeHTTPAddress\":\"taskmanager2:8042\",\"LastHealthUpdate\":1519568502259,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"datanode1\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"datanode1:45454\",\"NodeHTTPAddress\":\"datanode1:8042\",\"LastHealthUpdate\":1519260875647,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024}]";
public static void main(String[] args) {
JSONArray array = new JSONArray(sample);
for(int i=0; i < array.length(); i++){
System.out.println(array.get(i));
}
}
}
OUTPUT:
{"NodeManagerVersion":"2.8.3","Rack":"/default-rack","LastHealthUpdate":1519568501615,"HealthReport":"","State":"RUNNING","AvailableMemoryMB":1024,"NodeId":"taskmanager1:45454","UsedMemoryMB":0,"NodeHTTPAddress":"taskmanager1:8042","HostName":"taskmanager1","NumContainers":0}
{"NodeManagerVersion":"2.8.3","Rack":"/default-rack","LastHealthUpdate":1519260876106,"HealthReport":"","State":"RUNNING","AvailableMemoryMB":1024,"NodeId":"datanode2:45454","UsedMemoryMB":0,"NodeHTTPAddress":"datanode2:8042","HostName":"datanode2","NumContainers":0}
{"NodeManagerVersion":"2.8.3","Rack":"/default-rack","LastHealthUpdate":1519568502251,"HealthReport":"","State":"RUNNING","AvailableMemoryMB":1024,"NodeId":"taskmanager3:45454","UsedMemoryMB":0,"NodeHTTPAddress":"taskmanager3:8042","HostName":"taskmanager3","NumContainers":0}
{"NodeManagerVersion":"2.8.3","Rack":"/default-rack","LastHealthUpdate":1519260871527,"HealthReport":"","State":"RUNNING","AvailableMemoryMB":1024,"NodeId":"datanode3:45454","UsedMemoryMB":0,"NodeHTTPAddress":"datanode3:8042","HostName":"datanode3","NumContainers":0}
{"NodeManagerVersion":"2.8.3","Rack":"/default-rack","LastHealthUpdate":1519568502259,"HealthReport":"","State":"RUNNING","AvailableMemoryMB":1024,"NodeId":"taskmanager2:45454","UsedMemoryMB":0,"NodeHTTPAddress":"taskmanager2:8042","HostName":"taskmanager2","NumContainers":0}
{"NodeManagerVersion":"2.8.3","Rack":"/default-rack","LastHealthUpdate":1519260875647,"HealthReport":"","State":"RUNNING","AvailableMemoryMB":1024,"NodeId":"datanode1:45454","UsedMemoryMB":0,"NodeHTTPAddress":"datanode1:8042","HostName":"datanode1","NumContainers":0}
EDIT:
First, I removed the JSONTokener from the above code. Second, for completeness I'm adding the following code that shows how to find the individual JSON objects within the sample string using a regex as originally asked.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class orgJson1Main {
private static final String sample = "[{\"HostName\":\"taskmanager1\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"taskmanager1:45454\",\"NodeHTTPAddress\":\"taskmanager1:8042\",\"LastHealthUpdate\":1519568501615,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"datanode2\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"datanode2:45454\",\"NodeHTTPAddress\":\"datanode2:8042\",\"LastHealthUpdate\":1519260876106,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"taskmanager3\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"taskmanager3:45454\",\"NodeHTTPAddress\":\"taskmanager3:8042\",\"LastHealthUpdate\":1519568502251,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"datanode3\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"datanode3:45454\",\"NodeHTTPAddress\":\"datanode3:8042\",\"LastHealthUpdate\":1519260871527,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"taskmanager2\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"taskmanager2:45454\",\"NodeHTTPAddress\":\"taskmanager2:8042\",\"LastHealthUpdate\":1519568502259,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024},{\"HostName\":\"datanode1\",\"Rack\":\"/default-rack\",\"State\":\"RUNNING\",\"NodeId\":\"datanode1:45454\",\"NodeHTTPAddress\":\"datanode1:8042\",\"LastHealthUpdate\":1519260875647,\"HealthReport\":\"\",\"NodeManagerVersion\":\"2.8.3\",\"NumContainers\":0,\"UsedMemoryMB\":0,\"AvailableMemoryMB\":1024}]";
public static void main(String[] args) {
Matcher matcher = Pattern.compile("\\{[^}]*\\}").matcher(sample);
while(matcher.find()){
System.out.println(matcher.group());
}
}
}
To split on }, {, but retain the curly brackets in the tokens, split on this regex:
"(?<=\\}), (?=\\{)"
Which uses a look behind and a look ahead to assert the curly brackets preceed and follow the comma, but not consume them in the split.
The whole line then becomes:
List<String> res = Arrays.asList(temp.replaceAll("^.|.$", "").split("(?<=\\}), (?=\\{)");
Note also the simplified trimming of leading [ and trailing ] but more-simply removing the first and last character in one operation.
If your purpose to use this List as list of MyJsonObject I would recommend to reuse brilliant google gson library.
There is easy way to convert String to List without intermediate manipulation with List.
What you need to follow followed steps.
1) Create your POJO class:
public class POJO
{
String HostName;
String Rack;
String State;
String NodeId;
String NodeHTTPAddress;
String LastHealthUpdate;
String HealthReport;
String NodeManagerVersion;
String NumContainers;
String UsedMemoryMB;
String AvailableMemoryMB;
... getters/setters here ....
}
2) Create gson converter:
Gson gson = (new GsonBuilder() ).create();
3) Create typeToken for list of your POJOs:
Type type = new TypeToken< List<POJO> >(){}.getType();
4) Convert String to desire collection:
List<MyJsonObject> list = gson.fromJson( json, type );

How to parse a delimiter separated value with quoted characters and escape

I want to parse Delimiter Separated values with quoting characters and escape for quoting.
For example: a, "b""c""", d -> Expected to pare as three columns (a), (b"C"), (d) assuming comma as delimiter, quote is both quoting character and escape character.
I want to support multiple delimiters and enclosing characters also.
For example: a, "b""c"""|d -> Expected to pare as three columns if we use both comma and | used as delimiter.
Another example: a, <b\<c\>>|d -> Expected to parse as three columns if we use both comma and | as delimiters, < as left enclosure > as right enclosure and \ as escape.
Is it possible to create a parser combinator using JParsec?
After spending some time with API, I expected below code to work, but it is not working as expected to parse the above example.
Parser<?> quote_content = Scanners.notAmong(rightEnclose).many();
Parser<?> quoted = Scanners.nestableBlockComment(Scanners.among(leftEnclose),
Scanners.among(rightEnclose), quote_content);
Parser<?> unquoted = Scanners.notAmong(delimiter + leftEnclose);
Parser<?> chunk = Parsers.or(escapedSequence(), unquoted);
Parser<?> all = chunk().many1().source().sepBy(Scanners.among(delimiter));
Please suggest is it possible using JParsec, is there any better alternative?
Here is a basic working example using double quotes as string enclosing and doubling double-quotes to escape double-quotes (SQL-like strings...):
#Test public void test() throws Exception {
Parser<Void> escapingDoubleQuotesString = pattern(regex("((\"\")|[^\",])*"), "string");
Parser<String> quoted = escapingDoubleQuotesString //
.between(isChar('"'), isChar('"')).source() //
.map(unquoteString());
assertThat(quoted.parse("\"\"\"c\"")).isEqualTo("\"c");
Parser<String> unquoted = escapingDoubleQuotesString.source().map(unescapeQuotes());
assertThat(unquoted.parse("\"\"c")).isEqualTo("\"c");
Parser<List<String>> separated = quoted.or(unquoted).sepBy(pattern(regex("\\s*,\\s*"), "comma"));
assertThat(separated.parse("a,\"b\"\"c\"\"\", d")).containsExactly("a", "b\"c\"", "d");
}
private Map<? super String, ? extends String> unescapeQuotes() {
return new Map<String, String>() {
#Override public String map(String s) {
return s.replace("\"\"", "\"");
}
};
}
private Map<String, String> unquoteString() {
return new Map<String, String>() {
#Override public String map(String s) {
return unescapeQuotes().map(s.substring(1, s.length() - 1));
}
};
}
This could be improved by distinguishing quoted-strings content from unquoted strings content to allow using commas inside quoted strings. From this base it should be rather easy to add more separators or change the way strings are quoted/bracketed.
As a general guideline, using Test Driven Development to write jparsec parsers is a good combo. At the very least you should write unit tests to have a good understanding of how each parser works and how they combine.

Categories

Resources