Extract value using JSON Path from array - java

I have Json like this below
{"pd":"{\"e\":{\"h\":{\"ak\":\"120\",\"at\":\"app\"},\"b\":[{\"ts\":1319549658547,\"tz\":-400,\"s\":\"StartUpScreen\",\"et\":8,\"ev\":\"sessionStart\",\"si\":\"19477682-de55-414f-82c9-19bec331dc33\",\"tt\":{\"day\":\"Tuesday\"}},{\"ts\":132,\"tz\":-400,\"s\":\"StartUpScreen\",\"et\":3,\"ev\":\"AutomaticFeedRefresh\",\"si\":\"19477682-de55-414f-82c9-19bec331dc33\",\"tt\":{}},{\"ts\":131,\"tz\":-400,\"s\":\"MainScreen\",\"et\":3,\"ev\":\"MainScreen Event\",\"si\":\"19477682-de55-414f-82c9-19bec331dc33\",\"tt\":{}}],\"tt\":{\"OSV\":\"7.10\"}}}","serverPayload":{"httpHeaders":{"x-bluecoat-via":["35D3468EFF4D5F18"],"content-type":["application\/x-www-form-urlencoded"]},"senderIp":["101.100.000.100"]}}
I just need the values of ak, b [ts,si and tt[day]] and senderIp.
Now I have 2 questions, how do I extract all 'ts' attributes in 'b' and 'senderIp'. I have used the below code for ak, ts and si. I am not sure how I get 'tt', also while I run this code I get an exception like below
String pd = JsonPath.read(jsonString, "$.pd");
String ak = JsonPath.read(pd, "$e.h.ak");
String ak = JsonPath.read(pd, "$e.h.b[0]");
// String b = JsonPath.read(pd,"$.e.b[0][0]");
// String b = JsonPath.read(pd,"$.e.b[0][5]");
System.out.println("value of ak: "+ak);
Exception in thread "main"
java.lang.ClassCastException: net.minidev.json.JSONObject cannot be cast to java.lang.String.

$.e.h.b[0] looks like a JavaScript object (with fields including "ts" and "tz"), not a string. So it's reasonable for your JSON parser to treat it as a JSONObject rather than a string. Probably you need to drill down to $.e.h.b[0].ts or whatever field you're interested in. Something like this:
long ts = JsonPath.read(pd, "$e.h.b[0].ts");
I'm assuming it's your second String ak = line which causes the exception. I'm having trouble understanding your other question about the "ts" attributes. Maybe you could format the JSON string for easier reading?

Related

JSON File / Android - Get the value of string

I have the following JSON file format :
{"code":200,
"status":"OK",
"data":[
{"timings":
{"Fajr":"03:11 (EET)",
"Sunrise":"04:54 (EET)",
"Dhuhr":"11:53 (EET)",
"Asr":"15:29 (EET)",
"Sunset":"18:52 (EET)",
"Maghrib":"18:52 (EET)",
"Isha":"20:23 (EET)",
"Imsak":"03:01 (EET)",
"Midnight":"23:53 (EET)"},....
I want to get the value of Asr (for example) & parse it into string variable, I tried the below but nothing works (Please note: response is successfully retrieved, so no issue with reaching the JSON file, but only to get the value of string).
String mfajr = response1.getJSONArray("data").getJSONObject(0)
.get("Fajr").toString();
String mdoher = response1.getJSONArray("data").getJSONObject(0)
.getJSONArray("timings")
.get(Integer.parseInt("Dhuhr")).toString();
Assuming that response1 is a JSONObject.
String mfajr = response1.getJSONArray("data")
.getJSONObject(0)
.get("Fajr").toString();
That will fail because getJSONObject(0) returns an object that has a "timings" attribute ... not a "Fajr" attribute.
String mdoher = response1.getJSONArray("data")
.getJSONObject(0).getJSONArray("timings")
.get(Integer.parseInt("Dhuhr")).toString();
That will fail because the value of "timings" attribute is JSON object, not a JSON array.
Also, the value of the "Dhuhr" attribute is not an integer, so parseInt is not going to work. If you want the value as an integer, you are going to do some string analysis to convert "11:53 (EET)" to an integer.
Basically, you need to make sure that your Java code precisely matches the JSON structure. Close enough is NOT good enough.
OK .... so you want someone to write your code for you.
Try this:
String mfajr = response1.getJSONArray("data")
.getJSONObject(0)
.getJSONObject("timings")
.getString("Fajr");
Now, compare it with the structure of the JSON.

HttpServer Request get date range from query string

I am new to Java and Vertx and I have a query string with the following format:
GET /examples/1/data?date_1[gt]=2021-09-28&date_1[lt]=2021-10-28
Here I have this date_1 parameter which is within a certain range. I have been using HttpServerRequest class to extract simple parameters like integers but not sure how to proceed with these kind of range parameters.
With the simple parameters, I can do something like:
String param = request.getParam(paramName);
paramAsInteger = Integer.valueOf(paramAsString);
However, confused as to how to deal with the gt and lt options and the fact that we have same parameter twice.
You say that you have difficulties parsing out these tokens. Here's how you can handle this.
The first thing to understand is that the parameter name is NOT "date1"
There are actually two parameters here
2.1. "date_1[gt]" with a value of "2021-09-28"
2.2. "date_1[lt]" with a value of "2021-10-28"
This is because in the URI parameter definition everything before the "=" sign is the parameter name and everything after is the parameter value.
You can just do
String dateAsString = request.getParam("date1[gt]");
paramAsInteger = toDate(dateAsString)
To implement the toDate() function read this simple article how to convert a string object into a data object using a standard library
(link)
Vert.x will treat these parameters as two separate ones. So RoutingContext#queryParam("date_1[gt]") will only give you the value for [gt]. If you want the value for [lt] you need to get that separately.
That being said, you can move this tedious logic into an extra handler and store the values in the RoutingContext. Something like this might be easier:
private void extractDates(RoutingContext ctx) {
var startDate = ctx.queryParam("date_1[gt]");
var endDate = ctx.queryParam("date_1[lt]");
var parsedStartDate = DateTimeFormatter.ISO_LOCAL_DATE.parse(startDate.get(0));
var parsedEndDate = DateTimeFormatter.ISO_LOCAL_DATE.parse(endDate.get(0));
// things we put in the context here can be retrieved by later handlers
ctx.put("startDate", parsedStartDate);
ctx.put("endDate", parsedEndDate);
ctx.next();
}
Then, in your actual handler you can access the two dates as follows:
router.get("/date")
.handler(this::extractDates)
.handler(ctx -> {
var responseBody = ctx.get("startDate") + " - " + ctx.get("endDate");
ctx.end(responseBody);
});
This allows you to keep your actual business logic concise.

java.lang.String cannot be cast to java.lang.Integer JAVA Hibernate

i got an error after submit my set to database like this
java.lang.String cannot be cast to java.lang.Integer
And, i dont have no idea about to parse this List to integer
carFamilySelectList = new ArrayList<SelectItem>();
List<CarFamily> carFamilyList = carFamilyServiceImpl.selectCarFamilyIdList();
carFamilySelectList.add(new SelectItem("", "Select one"));
for(CarFamily as : carFamilyList) {
carFamilySelectList.add(new SelectItem(as.getCarFamilyId(), as.getCarFamilyName()));
}
Please help!
It's hard to say for sure without what line of code in the database(?) is throwing the exception but my guess is that the cause is that first list entry that's causing the problem:
carFamilySelectList.add(new SelectItem("", "Select one"));
I'm assuming that CarFamily.getCarFamilyId() returns an int, and that the return value of SelectItem.getValue() is being cast to an Integer somewhere? That first list entry is a SelectItem with an empty string as its value. Try using 0 (or -1 or whatever) instead:
carFamilySelectList.add(new SelectItem(0, "Select one"));
But in the future, include more relevant information in your question (the line where the exception is thrown and at least the signatures for the methods in your custom class that are relevant to your question... like getCarFamilyId() in this case).

How to get a protobuf repeated field builder in Java?

I want to convert an object of another format into a protobuf, knowing the protobuf's Descriptors. It's easy to do for regular fields or even a nested field. But, I'm running into a problem for repeated fields.
message Foo {
optional MsgA a = 1;
repeated MsgB b = 2;
}
For "MsgA a", the code bld.getFieldBuilder(field) works:
Foo.Builder bld = Foo.newBuilder();
Descriptors.Descriptor msgDesc = Foo.getDescriptor();
List<Descriptors.FieldDescriptor> fields = msgDesc.getFields();
for (Descriptors.FieldDescriptor field : fields) {
Message.Builder subBld = bld.getFieldBuilder(field);
// set foreign value xyz using subBld
// subBld.setFleld(subfield1, xyz);
}
But for "MsgB b", the same code throws "UnsupportedOperationException: getFieldBuilder() called on a non-Message type."
I understand the repeated field is a list, I may set each one separately. But, how do I get a builder first? Is there a clean and easy way to do the similar?
Thanks for any input.
You don't get a builder for the repeated field itself - you call Builder.addRepeatedField(field, value) etc. To get a builder for the type of the repeated field, you can use:
Builder builder = bld.newBuilderForField(field)
If you want to modify an existing value, you can use Builder.getRepeatedFieldBuilder(field, index).
To create an instance to start with, you can use Builder.newBuilderForField:
Message.Builder subBld = bld.newBuilderForField(field);
// Now modify subBld, then...
bld.addRepeatedField(field, subBld.build());

Java JSONArray from Javascript JSONArray

I am passing a json object from javascript to a java servlet using ajax.
var jsonObj = JSON.stringify(objArray); //Then I pass it to Java using ajax.
In my Java I am getting the json string from the request, then creating a jsonarray, then looping through that array and i'm getting errors when trying to pull one of the json objects from the array.
String dataObj = request.getParameter("obj");
String sql = request.getParameter("sql");
ArrayList<Object> returnArray = new ArrayList<Object>();
int key;
//Get type of object being passed.
JSONArray jsonArray = JSONArray.fromObject(dataObj);
for(int i=0; i<jsonArray.size(); i++) {
String obj = new Gson().toJson(jsonArray.getJSONObject(i)); //This is where i'm getting an error
String className = getClassName(jsonArray.getJSONObject(i));
Class targetClass = null;
try {
targetClass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Create Object
Object data = new Gson().fromJson(obj, targetClass);
I'm posting the relevant code, the for loop isn't closed because the rest of the code is quite long, and this is the part where i'm getting the error.
net.sf.json.JSONException: JSONArray[0] is not a JSONObject.
Here is what the json array looks like when its passed in from javascript. This is a println of the jsonArray object.
[{"number":"(123) 456-7050","type":"Home","contactId":1,"id":16662,"className":"beans.PhoneNumber","position":0}]
With one object in it, this code works. But as soon as I get 2 or more, my error comes up.
[[{"number":"(123) 456-7050","type":"Home","contactId":1,"id":16662,"className":"beans.PhoneNumber","position":1},{"number":"(555) 555-1233","type":"Mobile","contactId":1,"id":16656,"className":"beans.PhoneNumber","position":0},{"number":"(999) 999-9999","type":"Home","contactId":1,"id":16664,"className":"beans.PhoneNumber","position":3},{"number":"(222) 222-2222","type":"Home","contactId":1,"id":16666,"className":"beans.PhoneNumber","position":4}]]
It almost looks like when i'm passing more than one object, it create an array of an array, which could be why its not working. But how do I avoid doing that when i'm passing a jsonarray from javascript? Using just the dataObj I have no access to size or get to loop through it.
[
[
{
"number":"(123) 456-7050","type":"Home",
"contactId":1,
"id":16662,
"className":"beans.PhoneNumber",
"position":1
},
{
"number":"(555) 555-1233",
"type":"Mobile",
"contactId":1,
"id":16656,
"className":"beans.PhoneNumber",
"position":0
},
{
"number":"(999) 999-9999",
"type":"Home",
"contactId":1,
"id":16664,
"className":"beans.PhoneNumber",
"position":3
},
{
"number":"(222) 222-2222",
"type":"Home",
"contactId":1,
"id":16666,
"className":"beans.PhoneNumber",
"position":4
}
]
]
This is not an array of objects. This is an array of arrays of objects. According to your description, you are expecting something like the following to be fed to your Java:
[{"foo":"bar"}, {"bar":"baz"}]
But you are really trying to parse:
[[{"foo":"bar"}, {"bar":"baz"}]]
I am not completely sure, because you have not shared the json that you are trying to parse, but the most probable error you have is just what it says: the first element of the array is not JSONObject. Note that string values, lons and booleans are not JSONObjects. I would suggest you to use the more genereal JSONArray.get and check instance of what class it is. Maybe this can head you to the problem with the json you have. If I got it completely wrong - write back and I will try to help. In such a case it will be still useful to share the results of the proposed experiment.
EDIT:
This is double array -> maybe you using getJSONArray(int index) will help you. as the other answer mentioned - this is array of arrays. Also consider changing the javascript to reduce the level of arrays included.

Categories