I am writing an API in Java using Spark (irrelevant to my problem but that gives a bit of context).
I have the following JSON (exactly as it is returned by my back-end):
{"CfgCampaign":{"callingLists":{"CfgCallingListInfo":{"callingListDBID":{"value":126},"share":{"value":10},"isActive":{"value":2}}},"xmlns":"http://schemas.genesyslab.com/Protocols/Configuration/ConfServer/2005/","DBID":{"value":101},"name":{"value":"WI_Camp_1"},"state":{"value":1},"campaignGroups":{"CfgCampaignGroupInfo":[{"groupType":{"value":5},"dialerDBID":{"value":0},"optMethodValue":{"value":80},"origDNDBID":{"value":0},"numOfChannels":{"value":10},"groupDBID":{"value":826},"isActive":{"value":2},"scriptDBID":{"value":0},"trunkGroupDNDBID":{"value":0},"operationMode":{"value":1},"dialMode":{"value":2},"statServerDBID":{"value":176},"optRecBuffSize":{"value":6},"optMethod":{"value":1},"minRecBuffSize":{"value":4}},{"groupType":{"value":5},"dialerDBID":{"value":0},"optMethodValue":{"value":80},"origDNDBID":{"value":0},"numOfChannels":{"value":10},"groupDBID":{"value":827},"isActive":{"value":2},"scriptDBID":{"value":0},"trunkGroupDNDBID":{"value":0},"operationMode":{"value":1},"dialMode":{"value":2},"statServerDBID":{"value":176},"optRecBuffSize":{"value":6},"optMethod":{"value":1},"minRecBuffSize":{"value":4}}]},"scriptDBID":{"value":0},"tenantDBID":{"value":101}}}
It seems to be valid, as per https://jsonlint.com/
I store it in my code as a JSONObject (so basically, the above is the result of a toString()).
However, when I try to extract "campaignGroups" in a JSONArray, I get:
org.json.JSONException: JSONObject["campaignGroups"] not found.
I actually get this error even by just trying to get any key for that matter, e.g. calling get("DBID") will return the same error.
I am a bit confused as to what is going on here, and any help would be appreciated.
edit: Because it is only obvious from the exception, I am using json.org
Thanks !
I believe the error you're experiencing is due to the outer JSON object, "CfgCampaign", that contains the rest of your data. Some sample code for how to get around this using the org.json library is shown below:
// Loads the JSON (assuming you provide it as a string).
JSONObject x = new JSONObject(...);
// Gets and stores a reference to the outer object.
JSONObject y = x.getJSONObject("CfgCampaign");
// Now you can access any of the nested fields as follows.
JSONObject z = y.getJSONObject("campaignGroups");
Calling toString() on that object should return a string that looks something like "[Object Object]", if the toString method has to be called on it, then you'll also need to call JSON.parse(your_object_here) on it to access properties on it.
Also it looks like you'll need to be looking for your_object_name.CfgCampaign.campaignGroups or your_object_name["CfgCampaign"]["campaignGroups", but it's hard to tell without the code you're using to access campaignGroups.
If you set something like
const obj = {"CfgCampaign":{"callingLists":{"CfgCallingListInfo":{"callingListDBID":{"value":126},"share":{"value":10},"isActive":{"value":2}}},"xmlns":"http://schemas.genesyslab.com/Protocols/Configuration/ConfServer/2005/","DBID":{"value":101},"name":{"value":"WI_Camp_1"},"state":{"value":1},"campaignGroups":{"CfgCampaignGroupInfo":[{"groupType":{"value":5},"dialerDBID":{"value":0},"optMethodValue":{"value":80},"origDNDBID":{"value":0},"numOfChannels":{"value":10},"groupDBID":{"value":826},"isActive":{"value":2},"scriptDBID":{"value":0},"trunkGroupDNDBID":{"value":0},"operationMode":{"value":1},"dialMode":{"value":2},"statServerDBID":{"value":176},"optRecBuffSize":{"value":6},"optMethod":{"value":1},"minRecBuffSize":{"value":4}},{"groupType":{"value":5},"dialerDBID":{"value":0},"optMethodValue":{"value":80},"origDNDBID":{"value":0},"numOfChannels":{"value":10},"groupDBID":{"value":827},"isActive":{"value":2},"scriptDBID":{"value":0},"trunkGroupDNDBID":{"value":0},"operationMode":{"value":1},"dialMode":{"value":2},"statServerDBID":{"value":176},"optRecBuffSize":{"value":6},"optMethod":{"value":1},"minRecBuffSize":{"value":4}}]},"scriptDBID":{"value":0},"tenantDBID":{"value":101}}}
then to get the array in campaignGroups you'll need something to look like:
obj.CfgCampaign.campaignGroups
Related
Using an API, I am calling for an options chain with lots of different data. It looks like this:
```
[
putCall=PUT
symbol=AAPL_012023P100
description=AAPL Jan 20 2023 100 Put
exchangeName=OPR
bidPrice=10.05
askPrice=10.3
lastPrice=10.15
bidAskSize=78X102
markPrice=10.18
bidSize=78
askSize=102
lastSize=0
highPrice=10.15
lowPrice=9.85
openPrice=0.0
closePrice=9.98
totalVolume=334
quoteTimeInLong=1612904400035
tradeTimeInLong=1612903831902
netChange=0.17
volatility=37.645
delta=-0.195
gamma=0.004
theta=-0.014
vega=0.524
rho=-0.676
timeValue=10.15
openInterest=7941
isInTheMoney=false
theoreticalOptionValue=10.175
theoreticalVolatility=29.0
isMini=false
isNonStandard=false
optionDeliverablesList=<null>
strikePrice=100.0
expirationDate=1674248400000
expirationType=R
multiplier=100.0
settlementType=
deliverableNote=
isIndexOption=<null>
percentChange=1.75
markChange=0.2
markPercentChange=2.01
otherFields={lastTradingDay=1674262800000, daysToExpiration=709, tradeDate=null}
]], ```
This is one part of the many it returns. I need all of them. So, using Jackson I understand how to convert this to JSON using something like this:
```
ObjectMapper mapper = new ObjectMapper();
String data = eq.toString();
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(data);
Now, this cleans it up some, but now for what I actually need.. I need 3 things out of all this. I would like to create an object for each one of these things with the following fields: openInterest, totalVolume, and description.
I have tried searching for this, but I can't figure it out for when you have multiple values. What I posted above is just one of many entries that the API returns me. I would really appreciate some help :)
this:
[
putCall=PUT
symbol=AAPL_012023P100
/*bla di bla whatever*/
markPercentChange=2.01
otherFields={lastTradingDay=1674262800000, daysToExpiration=709, tradeDate=null}
]], ``
I'ma call this leSRC
JSONObject zTHING = new JSONObject();
zTHING.put("openInterest", leSRC.getJSONObject("openInterest"));
zTHING.put("totalVolume", leSRC.getJSONObject("totalVolume"));
zTHING.put("description", leSRC.getJSONObject("description"));
Your zTHING object should have those 3 KvP's set up correctly.
I was trying to write a data model to send a JSON to the API and delete some fields
the JSON should contain the id of some words and it should look exactly like this :
{
"words":[3,4,5]
}
as I know and also as the https://jsonformatter.org/ said the data class should be something like the following piece of code:
data class words(var id: List<Int>)
but the problem is when I pass the data to it and toast it to see if it's a valid JSON request for the server the output will be this :
words(id=[1,2,4,5])
and it's not what it should be.
as I said I need this :
{
"words":[3,4,5]
}
I think the following should work.
data class AnyNameYouWant(val words: List<Int>)
I think the name of the data class really doesn't matter as it would finally represent the { } object syntax of json.
Looking in the comments, I think it's better to use some logging library like Timber. If you are using Retrofit then use can also use HttpLoggingInterceptor and set the level to Body that will print the body of the response in the logcat.
I'm new, and attempting to work with the Rest API on setlist.fm from Android Studio, but am having some issues when fitting my GET request results into my Java data model.
Particularly, I have modeled "sets" ("set" refers to a set played at a concert) as a Java class. But commonly, I get results back from my HTTP requests that have "set" as an empty string or even an array.
I'll use this following GET request for all Radiohead setlists as an example:
http://api.setlist.fm/rest/0.1/artist/a74b1b7f-71a5-4011-9441-d0b5e4122711/setlists.json
Notice how, for the most part, "sets" is an object. But in some instances, it is a String. In other instances it is an array.
My Android Studio is giving me the following error when I try to parse the json with Gson into my data model using the following line of code:
gson.fromJson(result.toString(),Response.class);
It appears to be failing on an instance where "sets" is shown an empty string rather than an object:
Expected BEGIN_OBJECT but was STRING at line 1 column 942 path $.setlists.setlist[0].sets
Does anyone have advice on how to handle this type of thing? I've noticed it with all artists I've looked up so far.
Thanks!
Assuming Response is a class you wrote containing the main fields of the json and that at some point in it you have:
#SerializedName("setlist")
private List<MyItem> setlist;
I also assume your MyItem class contains the field:
#SerializedName("sets")
private List<MySet> sets;
if you let Gson parse it it will fail when it found a string instead of a list (-> array) of MySet object.
But you can write a custom TypeAdapter for your MyItem.
There's plenty of documentation about how to write a Gson TypeAdapter, look for it.
Use instanceOf operator to determine the type and cast accordingly.
JSONObject response=new JSONObject(res);
if(res.get("key") instanceOf JSONObject)
{
// code for JSONObject
}
else if(res.get("key") instanceOf JSONArray)
{
// code for JSONOArray
}
And so on
I am trying to add a function to a JSONJavaObject and calling it from a control on an xpage.
so far I have:
json = (JsonJavaObject) JsonParser.fromJson(factory, colJson);
String func = "function () { alert('you clicked?'); }";
json.put("onClick", new JsonReference(func) );
In the first line I add key-value pairs from a column in a Notes view.
In the second line I define the function as a string.
In the last line I place the converted string as function in the jsonjava object.
I read about this in the following blog post:
http://camerongregor.com/2016/01/19/doublequoteavoidance/
In the next step I bind the function to e.g. a button control as followed:
<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[obj.onClick]]></xp:this.script>
</xp:eventHandler>
</xp:button>
obj is the respresentation of the JSONJava object in SSJS.
But without success. Anyone know how I can call the function in the object?
I hope I will make sense here, let me know if anything to clarify.
If you are simply trying to dynamically output the client side script of a button event, then you don't need to use JsonReference at all. You can just use a String.
In my blog article I might not have make it clear why I needed to use JsonReference. I was using it in the process of rendering a custom UIComponent, part of this process required generating a Json object client side. To do this I created the JsonJavaObject as you did and then asked it to be turned into a string with the 'toJson' method. My problem was that when I asked the whole object to become a string, every property of that object that was a String, would begin and end with a double quote. I needed to ensure that the properties which were intended to be functions did not begin and end with "". By using the JsonReference the JsonGenerator became aware of my intention not to include these double quotes.
In your case, it looks as though you are just trying to dynamically determine what happens with onClick. To do this you could simply use a String instead of the JsonReference. The inclusion of the 'function() {}' is unnecessary as this will be generated when the event handler is rendered at the end of the page.
For Example here would be the Json Java Object
JsonJavaObject obj = new JsonJavaObject();
String func = " alert('you clicked?'); ";
obj.put("onClick", func);
return obj;
And here would be the button:
<xp:button id="button1" value="Alert Me">
<xp:eventHandler event="onclick" submit="false"
script="#{javascript: myBean.myObject.get('onClick')}">
</xp:eventHandler>
</xp:button>
This should give you the end result of seeing 'you clicked?' alert.
You can also inspect how this has all been generated in the script block near the end of the page using 'view Source' or your favourite web browser developer tools:
function view__id1__id2_clientSide_onclick(thisEvent) {
alert('you clicked?');
}
XSP.addOnLoad(function() {
XSP.attachEvent("view:_id1:_id2", "view:_id1:button1", "onclick",
view__id1__id2_clientSide_onclick, false, 2);
});
Let me know if anything isn't clear, hope it helps!
Does obj.onClick already give you a handle to the function returned by the Java class? If it does then you should be able to call it using the call or apply methods that are available in JavaScript:
obj.onClick.call();
obj.onClick.apply();
More details about those two methods can be found here: What is the difference between call and apply?
I'm passing a String parameter into a java function I wrote.
When I pass the string parameter the method is accepting my parameter as follows
http://mywebsite.com/getCity.php?StateID={"state":"Alabama"}
I want my method to accept my string parameter as follows
http://mywebsite.com/getCity.php?StateID=Alabama
How do I get rid of {"state":"Alabama"}?
Hey Guys,
I'm building an android app. My syntax below is definitely java. I'm going to show you where I'm having trouble. I'm having trouble on the first line of the method so to show you the entire method would be silly.
public JSONArray getDetails(String StateID) {
// this Log.e is showing {"state":"Alabama"}
// how do I get it to show Alabama?
Log.e("StateID= " + " = ", StateID);
}
You've got a JSON object there (and it really should be URL encoded if it's going to live on a URL like that).
Treat it like a JSON object and use JSONObject to decode it. Deal with the checked exception thrown however you see fit.
JSONObject jsonObject = new JSONObject(StateID);
System.out.println(jsonObject.getString("state"));
I'm don't know Java, but the best method would be to deserialize the string into a Java object that had a state property. See: http://www.javacreed.com/gson-deserialiser-example/
Alternatively, you could just do something ugly like this:
StateID.substring(10, StateID.length - 2)
Which should trim {"state":" off the front, and trim "} off of the back.