I have been trying to replace the dots with a different symbol using regex. But unable to add all the dots in capturing groups to replace. Basically this dots needs to be replaced only for keys.
I have tried with [\w\d]*([.])]* which gets me all the instances where dots exists with words. But unable to set it just for keys.
If at all try ending the expression with " and : like [\w\d]+?([.])]*?[\w\d]+?[":] it selects only the last part of the key or value.
{
"header": {
"dataModelVersion": "3"
},
"content": {
"sasl.kerberos.service.name": {
"displayName": "Kerberos Service Name",
"identifiesControllerService": false,
"name": "sasl.kerberos.service.name",
"sensitive": false
}
}
}
From your input json, here I have assume that there is no digit present on json key. So, there is no need to add \d on regex.
Here, I have replace dot (.) on json key with character underscore (_). Yes, you can replace with any character if you want.
Matcher matcher = Pattern.compile("\"([\\w\\.]*)\"[:]", Pattern.CASE_INSENSITIVE)
.matcher(json);
while(matcher.find()) {
if(matcher.group().contains(".")) {
json = json.substring(0, matcher.start())
+ matcher.group().replace(".", "_")
+ json.substring(matcher.end());
}
}
System.out.println(json);
Result of this program as below:
{
"header": {
"dataModelVersion": "3"
},
"content": {
"sasl_kerberos_service_name": {
"displayName": "Kerberos Service Name",
"identifiesControllerService": false,
"name": "sasl.kerberos.service.name",
"sensitive": false
}
}
}
Related
I am new to RedisSearch. I have a Java client. What is the easiest way to parse this sample FT.SEARCH result into JSON or POJO or something more useful?
Sample result from FT.SEARCH (actually a string):
[
3,
movie_json: 1, [$, { "id": 1, "title": "Game of Thrones" } ],
movie_json: 3, [$, { "id": 3, "title": "Looking for Sugarman" } ],
movie_json: 2, [$, { "id": 2, "title": "Inception" } ]
]
Something like this would be useful:
{
"count": 3,
"docs": [
{ "id": 1, "title": "Game of Thrones" },
{ "id": 3, "title": "Looking for Sugarman" },
{ "id": 2, "title": "Inception" }
]
}
The most obvious is a RegEx matcher as below (I am no regex expert).
This is the code generated by the https://regex101.com/ site where I can get the right groups on their site as long as I use a global flag - but it seems that Java doesn't have a GLOBAL pattern / flag! Is that true?
The code the site generated is below and sure enough matcher.find() shows no match, presumably due to the absence of the global flag.
final String regex = "(?<=\\[\\$, ).*?(?= \\])";
final String string = respContent; // The rediSearch result string shown above
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("Full match: " + matcher.group(0));
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
}
}
I could use the String.split() dance too.
However, is there an existing solution that is probably more robust for multiple FT.SEARCH results use-cases?
I imagined someone would have written a RedisSearch results parser by now but I cannot find one.
Thanks,
Murray
The high level Redis API for Quarkus only exposes the plain Redis commands as a set of java APIs. To handle Redis extensions, you can always refer to the low-level API: https://quarkus.io/guides/redis-reference
Once you choose the low-level API, you are, in fact, using the underlying driver that Quarkus uses. This is Vert.x Redis client.
In this mode, you can use any Redis extension and work with JSON directly, for example:
// set a JSON value
lowLevelClient
.send(cmd(Command.create("JSON.SET")).arg("foo").arg(".").arg("\"bar\""))
.compose(response -> {
// OK
// get a JSON value
return lowLevelClient.send(cmd(Command.create("JSON.GET")).arg("foo"));
})
.compose(response -> {
// verify that it is correct
should.assertEquals("\"bar\"", response.toString());
// do another call...
return lowLevelClient.send(cmd(Command.create("JSON.TYPE")).arg("foo").arg("."));
})
.compose(response -> {
should.assertEquals("string", response.toString());
return Future.succeededFuture();
})
.onFailure(should::fail)
.onSuccess(v -> {
test.complete();
});
While this mode is much more verbose, it gives you full control to the Redis extension you're using.
If the response can be mapped to JSON or is JSON already, you can get the content from its holder directly without need to parse the response, for example:
response.getKeys(); // returns the set of keys
response.get("key1"); // returns the JSON value for key "key1"
response.get(0); // returns the JSON value for array index 0
...
How to transform JSON response retrieved from external system to meaningful data (key/value pairs) in ESQL?
Retrieved JSON:
{
"data": [
{
"name": "application.info.header",
"value": "headerValue"
},
{
"name": "entity.statistics.name.fullName",
"value": "fullNameValue"
},
{
"name": "application.info.matter",
"value": "matterValue"
},
{
"name": "entity.statistics.skill",
"value": "skillValue"
}
]
}
where,
name ~ hierarchy of JSON (last attribute being the key)
value ~ value against the key
Expected JSON:
{
"data": {
"application": {
"info": {
"header": "headerValue",
"matter": "matterValue"
}
},
"entity": {
"statistics": {
"name": {
"fullName": "fullNameValue"
},
"skill": "skillValue"
}
}
}
}
Needless to say this can be easily achieved in Java through Split method - I'm looking for a suitable method in ESQL.
Current ESQL Module:
CREATE COMPUTE MODULE getDetails_prepareResponse
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
DECLARE data REFERENCE TO InputRoot.JSON.Data.data.Item[1];
SET OutputRoot.JSON.Data = InputRoot.JSON.Data;
SET OutputRoot.JSON.Data.data = NULL;
WHILE LASTMOVE(data) DO
DECLARE keyA CHARACTER SUBSTRING(data.name BEFORE '.');
DECLARE name CHARACTER SUBSTRING(data.name AFTER '.');
DECLARE keyB CHARACTER SUBSTRING(name BEFORE '.');
DECLARE key CHARACTER SUBSTRING(name AFTER '.');
CREATE LASTCHILD OF OutputRoot.JSON.Data.data.{EVAL('keyA')}.{EVAL('keyB')}
NAME key VALUE data.value;
MOVE data NEXTSIBLING;
END WHILE;
RETURN TRUE;
END;
END MODULE;
This is currently handled through SUBSTRING method in ESQL (for 3 levels only), but now the JSON levels are dynamic (no limit to key/value pairs) as per requirements.
You could implement your own procedure to split a string. Take a look at this answer for an example.
ESQL for splitting a string into mulitple values
The method splits S on Delim into an array in Env (Environment.Split.Array[]) and removes Environment.Split before refilling it.
I've got a chunk of JSON that looks like this:
{"id": "2345", "in": "sadfasd647", "name": "Delta", "created": "2018-01-19", "updated": ""}
Unfortunately, the service I'm sending this too doesn't handle blank entries. I have limited control over the source, so I'm looking for some Java Regex that I can use with ReplaceAll to get rid of all empty entries.
The result should look like:
{"id": "2345", "in": "sadfasd647", "name": "Delta", "created": "2018-01-19"}
The closest I've got is this:
string.replaceAll(",?\"*\":\\", "");
But I'm getting this error:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 7
Try this regex, also the first value could be blank and should still be replaced correctly:
(, "\w+": "")|("\w+": "",)
So your Java Code should look like this:
String json = "{\"id\": \"2345\", \"in\": \"sadfasd647\", \"name\": \"Delta\", \"created\": \"2018-01-19\", \"updated\": \"\"}";
String result = json.replaceAll("(, \"\\w+\": \"\")|(\"\\w+\": \"\",)", "");
System.out.println(result);
Which prints the following result:
{"id": "2345", "in": "sadfasd647", "name": "Delta", "created": "2018-01-19"}
Try this (assuming the id is never blank):
String json = "{\"id\": \"2345\", \"in\": \"sadfasd647\", \"name\": \"Delta\", \"created\": \"2018-01-19\", \"updated\": \"\"}";
json = json.replaceAll(", \"\\w+?\": \"\"", "");
System.out.println(json);
Regex: , "\w+?": ""
Output: {"id": "2345", "in": "sadfasd647", "name": "Delta", "created": "2018-01-19"}
You are getting that exception in your regex because of \\ at the end. This would be equal to a single \ for the regex, so it expects a character to be escaped after it, while you have none.
Try this
Try replacing any empty string or whitespace preceded and followed by a comma (or by [ or ] if it occurs exactly at the beginning or end of the list) with null. It should work whether the actual JSON string has whitespace or not.
String result = str.replaceAll("(?<=,|\\[)\\s*(?=,|\\])","null");
I have a string data which has some unwanted text. I want to delete that data from string using a regular expression. The example data is given below from which I want to eliminate the key meth and its corresponding data. The regular expression I created for this purpose is "meth(S+)([\\},])" but its not working.
I used the following code to use this regular expression:
json = json.replaceAll("meth(S+)([\\},])","");
Below is the string data that is present in json :
{
data: [
{
"city": "barcelona",
"Date": "4 Apr 2014",
"Name": "A-B",
"meth": function(){
return_LANG=="en-us"?"A-T": "A-T "
},
"fo": "null",
},
{
"city": "Newyork",
"Date": "4 Apr 2014",
"Name": "B-C",
"meth": function(){
return_LANG=="en-us"?"S-E": "शक्तिपुंजएक्स."
},
"fo": "null",
}
]
}
The result I am getting is the same string as my regular expression is unable to find the matching data in String.
Please help me correcting my regex.
This should do the trick:
json = json.replaceAll("(?s)meth.*?\\},", "");
Explanation:
(?s) is for multiline regular expressions. The dot . will then also match new line characters (equal to the flag DOTALL, see Pattern#DOTALL).
.*? searches any letter in a non greedy way till it finds the },
try this
s = s.replaceAll("(?s)\"meth\":.*?},\\s+","");
I want to get the value of id field in below string where the value of inuse field is 1 .
"version": "IPv6",
"primarywins": null,
"id": 3,
"updated": 1368803376681,
"description": null,
"inuse": 0,
"alias": "Shared MGMT"
},
{
"computernameprefix": null,
"protocol": "static",
"version": "IPv4",
"primarywins": null,
"id": 5,
"updated": 1368912314856,
"description": null,
"inuse": 1
I am trying below java code
String regex = "\"id\": ([0-9]|[0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9]),\n.*,\n.*,\n.*\"inuse\": 1";
Pattern index_pattern2 = Pattern.compile(regex,Pattern.DOTALL);
Matcher cMatcher2 = index_pattern2.matcher(The string mentioned above);
if(cMatcher2 != null && cMatcher2.find()
{
ipGrp = cMatcher2.group(1);
}
The value of ipGrp from the above code is always 3, whereas I would like to get the value as 5
Any suggestion as to how can I get the value of correct id field when the value of in use is 1
Use this regex instead:
"id": ([0-9]{1,4})[^}]*"inuse": 1
Escaped:
"\"id\": ([0-9]{1,4})[^}]*\"inuse\": 1"
What did I do here?
Change [0-9]|[0-9][0-9]|[0-9][0-9][0-9]|[0-9][0-9][0-9][0-9] into [0-9]{1,4}, which means there must be between 1 and 4 of [0-9].
Change ,\n.*,\n.*,\n.* to [^}]*, which means any characters except }.
Try this out.
(?s)"id":\s?(\d+),+.*?(?:"inuse":\s)(\d)
It captures both inactive and active, but you can filter the results. (?s) causes "." to capture newlines. The first capture group captures the id. The (?: cause the second group to be non-capturing. The second capture group captures the active flag. Good luck.