Why is this JSON String invalid? jQuery.parseJSON function throws invalid character - java

When trying to parse the JSON being returned by my Serlvet to my JSP page the following line of code is throwing a invalid character exception :
var obj = jQuery.parseJSON(data);
CLIENT SIDE CODE
<script type = "text/javascript">
function updateProgrammerDetails(site, Id) {
$.post('EngineAdminServlet',
{
action: "updateProgrammerMenu",
siteDetails: site,
ID: Id,
},
function(data, status){
var pid, name, sky, ip, eleven;
var obj = jQuery.parseJSON(data);
.........
}
}).fail(function(error) {
alert("Error retrieving details from server");
}); //end ajax call
}
</script>
JSON STRING GENERATED USING GSON
I've imported the GSON library in my Servlet class in order to convert my Java object 'ProgrammerForJSP' to a JSON string. This was recommended on other posts to avoid any typos when creating the JSON string myself. This is the string it returned:
{"ID":123,"siteName":"VEGAS","skyl":"WZ0019","ipAddress":"0.0.0.0","code":"L/BEG"}
SERVLET CODE
....
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
String gson = new Gson().toJson(myObject);
response.getWriter().write(gson);
} //end of method
I don't know if I'm missing a step or doing something wrong? My thought is that the IP address field might be throwing off the parser and breaking the code (hence the invalid character exception) because it contains period characters in it? I really have no idea.
EDIT
I'm using jquery-1.11.3.js

The error is because the $.post method has already detected a JSON response and parsed the result to an object for you. You are then trying to call parseJSON on an object instead of a JSON string, which results in the error you've seen. You simply need to remove the call to $.parseJSON. Try this:
function updateProgrammerDetails(site, Id) {
$.post('EngineAdminServlet', {
action: "updateProgrammerMenu",
siteDetails: site,
ID: Id,
}, function(data, status) {
var pid, name, sky, ip, eleven;
// work with the object in 'data' here, E.g:
console.log(data.ID, data.siteName); // = 123, 'VEGAS'
}).fail(function(error) {
alert("Error retrieving details from server");
}); //end ajax call
}

Related

Retrofit Put Request for Mlab

Hi I'm trying to send a PUT request using Retrofit that uses $addToSet to my Mlab Server. I can do this using Postman but I'm having trouble doing it using Retrofit.
The collection looks like:
[
{
"_id": {
"$oid": "5abe74bac2ef1603f4045686"
},
"email": "test#gmail.com",
"completedWalks": [
"South Leinster Way"
],
"favWalks": []
}
]
The post man request has the API key, Query, and then $addToSet is passed in the body as so.
And the response is:
I'm trying to do it like this in android.
Retrofit:
#PUT("databases/walks/collections/user")
Call<Update> addCompleted (#Query("apiKey") String apiKey,#Query("q") String Email, #Body Update Query);
My model:
public class Update {
#SerializedName("n")
private String n;
public String getN() {
return n;
}
public Update(String n) {
this.n = n;
}
}
Creating the update object:
String updateComplete = String.format("'$addToSet': {'completedWalks': '%s'}} ", TrailName);
final String query =String.format("{'email': '%s'}",email) ;
final Update queryComplete = new Update(updateComplete);
And the Request:
Call<Update> completeCall = apiService.addCompleted(mlabAPi, query, queryComplete);
completeCall.enqueue(new Callback<Update>() {
#Override
public void onResponse(Call<Update> call, Response<Update> response) {
Toast.makeText(getApplicationContext(),"Walk marked as Complete", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<Update> call, Throwable t) {
Log.e(TAG, t.getMessage());
}
});
But this only overwrites whats in the collection and I have:
[
{
"_id": {
"$oid": "5abe74bac2ef1603f4045686"
},
"n": "'$addToSet': {'completedWalks': 'Kerry Head Cycleway'}} "
}
]
Does anyone know where I'm going wrong, should I not be passing $addToSet as a model because it seems to be overwriting all, how do I pass it then?
Thank You.
#Body Update Query -- Retrofit will encode the object passed to this as JSON (assuming you are using the Gson converter, which it appears you are). That is where this "n": "'$addToSet': {'completedWalks': 'Kerry Head Cycleway'}} " is coming from. You need to structure you Java Object the same as your JSON object for gson to serialize it correctly.
I am not familiar with the mlab api, but from your postman, it looks like you want a request body something like this --
public class UpdateRequest {
#SerializedName("$addToSet")
Map<String, String> addToSet = new HashMap();
}
Update your interface to send this object as the body --
#PUT("databases/walks/collections/user")
Call<Update> addCompleted (#Query("apiKey") String apiKey,#Query("q") String Email, #Body UpdateRequest Query);
And create the request body --
UpdateRequest requestBody = new UpdateRequest();
requestBody.addToSet.put("completedWalks", Trailname);
and create the call --
Call<Update> completeCall = apiService.addCompleted(mlabAPi, query, requestBody);
For further debugging, you can see what is actually being sent in your logcat by adding HttpLoggingInterceptor to your retrofit instance.
See here for setup. Then you can compare what your app is sending vs postman and see where things might be going sideways.

IllegalStateException:Target object must not be null Spring Boot

I am developing a platform based on the micro services architecture (JAX-RS) and a nodeJS API.
I have a problem adding an object to the database, because it always marks null by spring boot.
*Here is my REST controller code (JAX-RS):
#RequestMapping(value="/Add")
public Actifs AjouterActifs( #RequestBody Actifs act){
return Actif.saveT(act);
}
*Here the code node API to add the object "Actifs":
app.post("/act/add",function (req,res) {
var addActif = JSON.stringify(req.body);
console.log("params: "+addActif);
try {
http.get(url+"/Add",+addActif, function (response) { //problem is here "addActif is null"
var dataJson ='';
response.on('data',function(data){
dataJson += data;
});
response.on('end',function(){
try
{
var addAct = JSON.parse(dataJson);
}
catch(err) {
console.log('erreur de retourner l\'actif -->', +err);
}
res.json(addAct);
});
});
}
catch(e) {
console.log("erreur d'ajouter les info d'actif -->", +e);
}
});
*Postman:
I get this error:
org.springframework.http.converter.HttpMessageNotReadableException:
Required request body is missing:
How to avoid a null object passing from node JS to the JAX-RS service ?
thank you for helping me,
You are sending the actif to be added as a query parameter
http.get(url+"/Add?act="+addActif, function (response) {
...
}
But your SpringMVC Endpoint expects to find the Actif object in the request body
#RequestMapping(value="/Add")
public Actifs AjouterActifs( #RequestBody(required=false) Actifs act) {
...
}
Option 1: Use #RequestParameter("act") Actifs act and register an editor to parse the object from the query parameter string (see this question).
Option 2: Actually send the Actif json as the request body, e.g. by performing a POST request to url + "/Add" instead of a GET. You will have to use http.request to implement that.
Furthermore I would suggest to use #RequestBody (without required=false). That ensures that the parameter must be non-null and lets the application fail fast if that is not the case.
I solved the problem by changing the code like this
app.post("/act/add",function (req,res) {
var addActif = JSON.parse(req.body); //parse object
console.log("params: "+addActif);
try {
http.get(url+"/Add",addActif, function (response) { // delete '+'
var dataJson ='';
response.on('data',function(data){
dataJson += data;
});
response.on('end',function(){
try
{
var addAct = JSON.parse(dataJson);
}
catch(err) {
console.log('erreur de retourner l\'actif -->', +err);
}
res.json(addAct);
});
});
}
catch(e) {
console.log("erreur d'ajouter les info d'actif -->", +e);
}
});

Spring MVC: Show data in a dialog after making an AJAX call

I am new to Spring and web technology.
I have an table which contains a column with hyperlink. When I click on the hyperlink of a row, I need to display that rows data along with other details in a dialog. My controller method returns a ModelAndView which contains the data I need to show and the display page.
Problems:
How to show the dialog? and
How to pass the data to the dialog?
Table.jsp
<script type="text/javascript">
function showDialog(ref, date) {
$ajax({
type: "POST",
url: "/example/show.htm",
data: {
ref: ref,
date: date
}
success: function(data) {
},
error: function(data) {
}
});
}
</script>
Mapping
#RequestMapping(value = "show.htm", method=RequestMethod.POST)
public ModelAndView show(#RequestParam("ref") String ref, #RequestParam("date") String date,
HttpServletRequest request, HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView();
try {
SampleDTO SampleDTO = new SampleDTO();
sampleDTO.setDate(sdf.parse(date));
sampleDTO.setRef(ref);
SampleDTO billDto = // server call modelAndView.addObject("showBill", sampleDto);
modelAndView.setViewName("Dialog");
}
return modelAndView;
}
Your code is wrong, you are messing things, if you want to use jQuery and ajax calls then don't use ModelAndView in your Spring controller. Instead of that, use the following and return your bean or dto as a json using Jackson library from Java:
Include this jar in your lib project folder:
http://www.java2s.com/Code/JarDownload/jackson/jackson-all-1.9.9.jar.zip
Java code:
#RequestMapping(value = "businessBill.htm", method = RequestMethod.POST)
#ResponseBody
public String handleBusinessBillDetails(#RequestParam("reference") String billReference, #RequestParam("invoiceDate") String billDate,
HttpServletRequest request, HttpServletResponse response) {
String json = null;
try {
//1. Create 'jackson' object mapper
ObjectMapper objectMapper = new ObjectMapper();
BusinessBillDTO businessBillDTO = new BusinessBillDTO();
businessBillDTO.setBillDate(sdf.parse(billDate));
businessBillDTO.setBillReference(billReference);
BusinessBillDTO billDto = accountStatementBO.getBusinessBillDetails(businessBillDTO);
//2. Convert your 'bean' or 'dto' as 'json' string
json = objectMapper.writeValueAsString(billDto);
} catch (Exception ex) {
LOGGER.error(ex);
}
return json;
}
Then, in Table.jsp put the div used in Dialog.jsp as hidden, this will be your modal dialog in future (note that there are some changes in the span tags also):
<div id="BusinessBill" style="display:none;">
<h2>Bill Details</h2>
<em>Business Ltd</em>
<div class="row">
<span class="spanAsLabel">Account number</span>
<span id="dlg-account-number" class="spanAsLabel"></span>
</div>
<div class="row">
<span class="spanAsLabel">Bill date</span>
<span id="dlg-bill-date" class="spanAsLabel"></span>
</div>
</div>
Now fix your getBusinessBill(..) method like this:
You can also use $.ajax and maybe handle more states like onerror and others but this way is simpler (at least for me, you just need to evaluate if the returned data is null or not and let know the user - if null - that something happened at server side, maybe showing an alert with a generic message) - please read comments.
function getBusinessBill(billReference, billInvoiceDate) {
$.post("/AccountStatement/businessBill.htm", {
reference: billReference,
invoiceDate: billInvoiceDate
}, function (data) {
/* You can implement more validations for 'data', in my case I just used these 'if' conditionals but can vary. */
if(data != null) { //returned 'data' is not 'null'
/* parse 'data' as 'json' object
* will be good to console.log(data) and take a look. */
var obj = $.parseJSON(data);
if(obj != {}) { //check if 'data' is not an empty 'json' object once transformed
//set the 'data' in the dialog
$('#dlg-account-number').text(obj.accountNumber);
$('#dlg-bill-date').text(obj.billDate);
/* open modal dialog, you can simulate it this way (for this case)
* but the correct way is to use 'jquery-ui' dialog or any plugin you prefer.
* At this point you will see the hidden 'div' in a visible way with your 'data'.
*/
$('#BusinessBill').fadeIn();
} else {
//show 'generic' message
alert('No results found.');
}
} else {
//show 'generic' message
alert('An error occurred, try again.');
}
});
}
Finally, if everything is correct, you will see at the same page (Table.jsp) the modal dialog with your data, all made by an ajax call to avoid redirection pages like (Table.jsp to => Dialog.jsp).

Pass json object to a play-framework action

I am currently using Play v1.2.3. I have an endpoint to which I want to send a json object which will be deserialized into a Java object. So, I have something that looks like this:
public class UserController extends Controller {
public static class FullName {
public String first;
public String last;
}
public static void putName( FullName name ) { ... }
}
##### routes
PUT /user/name UserController.putName
With that in place, I would hope to call the endpoint with the given javascript:
$.ajax({
type: "PUT",
data: { first: "Michael", last: "Bailey" },
url: "/user/name"
});
Unfortunately, with the above setup, it seems that play is not wanting to send the entire data object, but is instead attempting to populate two parameters (first and last). Is there a way to define the endpoint to consume the complete body directly, or does it have to be done by hand?
To cast the entire input body into a Model class:
public static void create(JsonObject body) {
CaseFolder caseFolder = new Gson().fromJson(body, CaseFolder.class);
caseFolder.user = getConnectedUser();
if(caseFolder.validateAndSave()) {
renderJSON(
new JSONSerializer()
.exclude("*.class")
.exclude("user")
.serialize(caseFolder));
} else
error();
}
Also, the above code takes the resulting Model object and serializes it back out to JSON as the response body.
If you want to just access certain fields within the JSON request, you can use:
public static void update(JsonObject body) {
try {
Long id = (long) body.get("id").getAsInt();
CaseFolder cf = CaseFolder.loadAndVerifyOwner(getConnectedUser(), id);
cf.number = body.get("number").getAsString();
cf.description = body.get("description").getAsString();
if(cf.validateAndSave())
ok();
else
error();
}
catch (NullIdException e) {error();}
catch (NotFoundException e) {notFound();}
catch (NotOwnerException e) {forbidden();}
catch (Exception e) {e.printStackTrace(); error();}
}
Play's action method parameter binding mechanism does not accept JSON. You need to bind it manually. In your example, the code could be something like:
public static void putName( String data ) {
FullName fname = new Gson().fromJSON(data, FullName.class);
...
}
Note, Gson is provided with play!framework distribution, so you are free to use it
With your settings play is expecting params with names "name.first" and "name.last" and you are sending "first" and "last". Try with this ajax post
$.ajax({
type: "PUT",
data: {
name: {
first: "Michael",
last: "Bailey"
}
},
url: "/user/name"
});

json string can't be posted as plain string through jquery ajax?

I want to post a json string as plain string to a action ,then convert the string to List using gson, but the string is still treated as json object by jquery/webwork, I'm using jquery 1.43+webwork+gson, no jquery json plugin or something.
here is action:
public class ImageAction extends BaseAction {
private String pks;
public void setPks(String pks) {
this.pks = pks;
Gson gson=new Gson();
List<Map> list=gson.fromJson(pks,new TypeToken<List<Map<String,String>>>(){}.getType());
System.out.println(list.size());
}
......
}
jquery code:
j$.ajax({
url:approveUrl,
data: {pks:'[{"userName":"theoffspring"}]'},
// dataType:'json',
type:'post',
// traditional: true,
success:function (response) {
hideProgressBar(parent.document)
if (response.result==false){
alert(response.msg);
return;
}
// document.location.reload();
}
})
I want pks posted as a common string instead of json object. But setPks method turns out not to be invoked when I invoke the jquery code. So strange.
you have'nt serialized the data you are sending through ajax.serialize it at client using JSON.stringify() and send it will be converted to a single string.
modify your code to:
$.ajax({
url:approveUrl,
data:JSON.stringify(yourdata),
// dataType:'json',
type:'post',
// traditional: true,
success:function (response) {
hideProgressBar(parent.document)
if (response.result==false){
alert(response.msg);
return;
}
// document.location.reload();
}
})
this might work.
Have a look at this: http://jsfiddle.net/flocsy/vuGL9/
You'll see that your pks is actually sent as a string as you want it, when it's not sent as a string (pks2) it'll look different.
PS: look at the network tab in firebug or inspect element, depending on your browser:
pks: '[{"userName":"theoffspring"}]'
pks2[0][userName2]:'hehe'
So probably your server side does some magick...

Categories