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
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 trying to redirect to a controller method which is taking Long and String as argument by using the reverse controller. I use version 2.4 of the play framework.
I've defined this route in the routes file:
GET /games/play/:id controllers.Games.renderGame(id: Long, feedback: String = "")
To call this route, I'm using in a other method redirect():
return redirect(controllers.routes.Games.renderGame(gameId, "test"));
And here is my renderGame() method:
public Result renderGame(Long id, String feedback) {
//do something
return ok(...);
}
In my opinion this actually should work but play gives me a error:
error: method renderGame in class ReverseGames cannot be applied to
given types;
IntelliJ is trying to do it better:
Error picture
If I define the method just with Long as parameter it's working fine but when a add the String I get the error again.
Any idea what's wrong here?
Related to this Question, it actually should work: Play Framework: Redirect to controller method with arguments
I fixed the problem by myself but it tooks me hours. The problem was that I used a = instead of =?. It has to look like this:
GET /games/play/:id controllers.Games.renderGame(id: Long, feedback: String ?= "")
I think the problem is with the route definition try adding feedback params at the url pattern
GET /games/play/:id/:feedback controllers.Games.renderGame(id: Long, feedback: String = "")
cheers.
I'm trying to configure a request to http: //where.yahooapis.com/v1/places.q(name_here);count=50?....
Not the best solution, I guess, but I tried
#GET("/v1/{location}")
Places getLocations(#Path("location") String locationName);
and pass there
getLocations("places.q(" + locationName + ");count=50");
But it still doesn't work as the string (); is translated into %28%29%3B.
Can you suggest any solutions? It would be better to dinamycally modify only the name_here part, something like
#GET("/v1/places.q({location});count=50)
If it is not possible how do I have to pass symbols (); so that they are converted correctly?
I just tried
#GET("/v1/places.q({location});count=50")
Places getLocations(#Path("location") String name)
a bit later and it works fine. I thought it will insert something like "/" or modify it, but it does exectly what I need.