Android Phonegap - Passing JSONObject to javascript - javascript

I'm trying to pass some information from an Android native class to the javascript.
I'm taking a bundle, converts it to JSONObject and passing the string representation of it.
But when trying to parse it in the JS, it fails.
This is what I do:
JSONObject jsonObject = new JSONObject();
for (String key : bundle.keySet()) {
Object value = bundle.get(key);
try {
jsonObject.put(key, value.toString());
} catch (JSONException e) {
// Do nothing
}
}
final String jsStatement = String.format(
"window.doSomething('%s');", jsonObject.toString());
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
webView.loadUrl("javascript:" + jsStatement);
}
});
Can you tell me why it's not being parsed in the JS and how can I solve it?

Look into the Javascript Interface annotation which can be used to pass in / access the values from Java directly

Related

Passing dates between c# and javascript

I have an ASP.Net MVC app that returns a view model, which when converted to JSON using system.web.mvc.jsonresult looks as follows:
On the client I'm using KnockoutJS. I use MomentJS to format the value for the VoucherDate so that it can be displayed for humans:
var recsArray = [];
$.each(data.Vouchers, function (key, value) {
recsArray.push(
new edited(
interchangeId,
value.SupplierIsValid,
value.VoucherNo,
value.LegacySupplierId,
value.Transactions,
moment(value.OriginalVoucher.VoucherDate).format('YYYY/MM/DD HH:mm'),
value.OriginalVoucher
)
);
As you can see from the previous code snippet, in addition to pushing the data into an observable array for display in a KOGrid, I also push the entire "OriginalVoucher". This enables the user to edit the value for "LegacySupplierId" and click "Resubmit" which posts back the entire view model as seen below:
self.resubmit = function () {
var data = {
Vouchers: ko.toJS(this.recs),
BatchId: self.batchId(),
InterchangeId: interchangeId,
IsReadWrite: self.isReadWrite,
Interface: self.interface,
ReportClient: self.reportClient
};
$.ajax({
type: "POST",
url: BASE_URL + 'EditBatch/ResubmitRejectedVouchersAsNewBatch',
data: ko.toJSON(data),
I've checked using Fiddler and confirmed that the VoucherDate fields contain values such as /Date(14543712000000)/. My problem is, when reading in the C# controller, all of the dates are presented as 1/1/0001 12:00:00 AM.
I've read that javascript has a date.toISOString() function to convert to a format that C# will be happy with. Is there a better way that trying to find each date field in the javascript view model and executing a conversion against each before posting back to the C# controller
I think I have previously solved this problem using automapper by following instructions here: enter link description here
In my source code I can see that I created the following class but I don't know how / if this gets used:
public class JsonDateTimeTypeConvertor : ITypeConverter<string, DateTime>
{
public DateTime Convert(ResolutionContext context)
{
string jsonDate = context.SourceValue.ToString();
string offsetAsString = Regex.Match(jsonDate, #"\d+").Value;
double offset = System.Convert.ToDouble(offsetAsString);
DateTime ret = DataUtils.ConvertFromUnixTimestamp(offset);
return ret;
}
}
I think it was being used but I've inadvertently disabled it. This probably happened when I changed the type for the ViewModel received by the controller. The previous version of the application worked, so I guess the datetime was being converted correctly - probably by this automapper extension. I have pulled the old version of the code from TFS but can't figure out how it's doing the magic - I wish I'd made better notes at the time! All I have is:
I needed to create a custom type convertor to deal with JSON dates being passed to the EditBatch controller in the format of number of milliseconds since 1900.
I followed the wiki documentation from here:
https://github.com/AutoMapper/AutoMapper/wiki/Custom-type-converters
May be you can use a regex pattern like this. The following code shows ToJavaScriptDate() function that does this for you:
function ToJavaScriptDate(value)
{
var pattern = /Date\(([^)]+)\)/;
var results = pattern.exec(value);
var dt = new Date(parseFloat(results[1]));
return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
}
The ToJavaScriptDate() function accepts a value in /Date(ticks)/ format and returns a date string in MM/dd/yyyy format. Inside, the ToJavaScriptDate() function uses a regular expression that represents a pattern /Date(([^)]+))/.
The exec() method accepts the source date value and tests for a match in the value. The return value of exec() is an array. In this case the second element of the results array (results[1]) holds the ticks part of the source date. For example, if the source value is /Date(836418600000)/ then results[1] will be 836418600000. Based on this ticks value a JavaScript Date object is formed. The Date object has a constructor that accepts the number of milliseconds since 1 January 1970. Thus dt holds a valid JavaScript Date object. The ToJavaScriptDate() function then formats the date as MM/dd/yyyy and returns to the caller.
I'm really not a fan of the way the default JavaScriptConverter handles dates. I use the following class. (The CustomString class is kind of a dirty hack to get around the fact that the Serialize command is expected to return an IDictionary. See blog post here: http://blog.calyptus.eu/seb/2011/12/custom-datetime-json-serialization/)
public class DateTimeJsonSerializer : JavaScriptConverter
{
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
if (dictionary == null)
return null;
return new JavaScriptSerializer().ConvertToType(dictionary, type);
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
if (!(obj is DateTime)) return null;
return new CustomString(((DateTime) obj).ToString("yyyy-MM-ddTHH:mm:ss.fffZ"));
}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type> { typeof(DateTime), typeof(DateTime?) }); }
}
}
public class CustomString : Uri, IDictionary<string, object>
{
public CustomString(string str) : base(str, UriKind.Relative)
{}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public bool Remove(KeyValuePair<string, object> item)
{
throw new NotImplementedException();
}
public int Count { get; private set; }
public bool IsReadOnly { get; private set; }
public bool ContainsKey(string key)
{
throw new NotImplementedException();
}
public void Add(string key, object value)
{
throw new NotImplementedException();
}
public bool Remove(string key)
{
throw new NotImplementedException();
}
public bool TryGetValue(string key, out object value)
{
throw new NotImplementedException();
}
public object this[string key]
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public ICollection<string> Keys { get; private set; }
public ICollection<object> Values { get; private set; }
}
To use this in asp.net, I have the following section in my web.config (make sure to replace "AssemblyNameGoesHere" with the assembly that contains the converter class:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="2147483644">
<converters>
<add name="DateTimeConverter" type="DateTimeJsonSerializer,AssemblyNameGoesHere" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
I managed to work-around this by changing the data type on the "VoucherDate" field in the C# model from DateTime to String. I don't currently understand why this works. I also think there must be a better way!?

Return JavaScript object literal, not JSON string, from ASP.NET MVC endpoint

For various reasons, I have switched from ASP.NET MVC's built in JSON serializer (the one that returns a System.Web.Mvc.JsonResult object (see edit below)) to Newtonsoft. I didn't realize until after I began testing that the former returns a JavaScript object literal, while Newtonsoft returns a JSON formatted string.
I like not having to parse JSON strings on the client side — having it already as an object literal is very convenient — but I want to stick with Newtonsoft for other technical reasons.
For example, instead of seeing this result on my client...
"{"Errors":["Please enter a valid email address."],"HasErrors":true}"
...I'd like to see this result:
{"Errors":["Please enter a valid email address."],"HasErrors":true} // no quotes
Is there a way to make Newtonsoft return JS object literals instead of strings?
EDIT
The way my question was framed wasn't the best. There's nothing wrong with the JsonResult type. In fact, the solution still uses it. The only problem was the default Controller.Json methods, which can be overridden to use Newtonsoft (Json.NET) instead of the built-in serializer.
Just write a custom JsonResult that uses Newtonsoft serializer:
Something along the lines:
public abstract class BaseController : Controller
{
protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding)
{
return new JsonNetResult
{
ContentType = contentType,
ContentEncoding = contentEncoding,
Data = data
};
}
protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new JsonNetResult
{
ContentType = contentType,
ContentEncoding = contentEncoding,
Data = data,
JsonRequestBehavior = behavior
};
}
}
JsonNetResult.cs:
using System;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;
public class JsonNetResult : JsonResult
{
public JsonSerializerSettings SerializerSettings { get; set; }
public Formatting Formatting { get; set; }
public JsonNetResult()
{
Formatting = Formatting.None;
SerializerSettings = new JsonSerializerSettings();
JsonRequestBehavior = JsonRequestBehavior.DenyGet;
}
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (JsonRequestBehavior == JsonRequestBehavior.DenyGet
&& String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
}
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = !string.IsNullOrEmpty(ContentType)
? ContentType
: "application/json";
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
if (Data != null)
{
var writer = new JsonTextWriter(response.Output) { Formatting = Formatting };
var serializer = JsonSerializer.Create(SerializerSettings);
serializer.Serialize(writer, Data);
writer.Flush();
}
}
}
Credit: https://gist.github.com/jpoehls/1424538
Answer is here: How to force ASP.NET Web API to always return JSON?
Excerpt:
Clear all formatters and add Json formatter back.
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
EDIT
I added it to Global.asax inside Application_Start().

How can I call a server side c# method via javascript without a WebMethod or Updatepanel?

I would prefer not to use an update panel and using the common WebMethod approach leads me to this error with this code
private string currentHtml() {
StringWriter str_wrt = new StringWriter();
HtmlTextWriter html_wrt = new HtmlTextWriter(str_wrt);
Page.RenderControl(html_wrt);
return str_wrt.ToString();
}
[WebMethod]
public static void EmailPtoRequest() {
string test = currentHtml();
}
Error 8 An object reference is required for the non-static field, method, or property 'PtoRequest.cs.WebForm1.currentHtml()
Clearly the method being static is causing a bunch of headaches.
Is there a standard that I can use for this type of functionality? The goal is to allow the user to send their data to the server without causing a post and refreshing the page.
Note: I DO NOT want to use a webmethod as it is causing an error which does not let me compile.
public partial class WebForm1 : System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
}
private string currentHtml() {
StringWriter str_wrt = new StringWriter();
HtmlTextWriter html_wrt = new HtmlTextWriter(str_wrt);
Page.RenderControl(html_wrt);
return str_wrt.ToString();
}
[WebMethod]
public static void EmailPtoRequest() {
WebForm1 WebForm1 = new WebForm1();
string test = WebForm1.currentHtml();
}
}
Results in 'test' being an empty string instead of the html of the page.
private static string currentHtml() {
StringWriter str_wrt = new StringWriter();
HtmlTextWriter html_wrt = new HtmlTextWriter(str_wrt);
Page.RenderControl(html_wrt);
return str_wrt.ToString();
}
[WebMethod]
public static void EmailPtoRequest() {
string test = currentHtml();
}
}
Results in the first error again, but in the currentHtml method instead.
Please remember the question is not about the error, but an alternative to webmethod or update panels. Thank you.
3 options:
Make the currentHtml method static,
Instantiate the class that contains currentHtml like this:
new MyClass().currentHtml();
Use an ajax enabled wcf service.

Asynchronous JSON String loading JavaScript

I'm using the d3 force directed graph to display some data I get from an API. Before I can display it, it runs through a java class, which does write it into the right json format.
Since the programm runs in a JavaFX WebView I have a bridge class, that does have a getter method I can call from the JavaScript.
In my Main class I create a WebView and assign the bridge to it. I initialize my JSON translator and pass the bridge to it.
#Override
public void start(Stage stage) {
try {
new JsonTranslator(individual, depth, bridge);
Scene scene = createScene();
[...]
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
private Scene createScene() {
[...]
try {
JSObject jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("java", bridge);
} catch (Exception e) {
e.printStackTrace();
}
[...]
}
In my JSONTranslator class I write the json and pass it to the bridge
private void writeFile() {
try {
bridge.setJSONObject(obj.toJSONString());
FileWriter file = new FileWriter(
"C://path/to/some/file.json"
file.write(obj.toJSONString());
file.flush();
file.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Object:" + obj);
}
I also write it to a file. The data gets printed as expected. Now in my bridge the data is available throughout the getter / setter. In JSToFXBridge.java:
public String getJSONObject(){
System.out.println("get request: " + json);
return json;
}
public void setJSONObject(String string){
this.json = string;
}
Now I call it from my JavaScript
[...]
var draw = function(json, callback) {
[...]
callback.call(data);
};
var data = java.getJSONObject();
draw(data);
However it does print get request: -my json data- on the console, the json string is compleatly fine. If I copy & paste it from the console to be like this var data = -my json data- in the code it works. Only to asign it directly from the method won't work. I can't figure out why since I try to load it asynchronously. Based on this tutorial. Do I make a mistake in laoding the string? Or is it even a wrong way to do so?
Good answer / tutorial to asynchronous JavaScript callbacks can be found here. Solution, which created a new problem [ solved as well ], provided here.
In general think of this pattern:
function addOne(thenRunThisFunction) {
waitAMinuteAsync(function waitedAMinute() {
thenRunThisFunction()
})
}
addOne(function thisGetsRunAfterAddOneFinishes(){})
Explains it very well

How can i convert JSON to Java object

Hi I am having a JSON of following format
{
"elements":[
list1,
list2,
list3
]
}
where list1,list2,list3 are all javascript arrays.
Now I am able to pass this to my controller(am using spring mvc) from a javascript file. Now I want to use the data in the JSON that am sending. I want to map this to a model class and return it another jsp page.
I didn't create a model yet. how can i pull this off?
Please help. Thanks in advance.
use GSON to convert your JSON into java
YourModelClass obj= gson.fromJson(json, YourModelClass .class);
Using Gson, you first need to create a class structure representing your JSON data, so you can create a class like this:
public class Response {
private List<List<YourObject>> elements;
//getter and setter
}
Note that I use class YourObject since you don't specify what type your arrays contain... If the arrays contain just strings for example, replace YourObject by String. If the arrays contain a different object you have to create a class representing the data in your JSON, such as:
public class YourObject {
private String attribute1;
private int attribute2;
private boolean attribute3;
//getters and setters
}
Then, in order to actually parse your JSON response, you just have to do:
Gson gson = new Gson();
Response response = gson.fromJson(yourJsonString, Response.class);
And your JSON data will be used to fill your class structure, so you can access the fields, for example:
String attribute1 = response.getElements().get(i).get(i).getAttribute1();
Hi I used the following code and its working great.
Gson gson = new Gson();
JsonParser jsonParser = new JsonParser();
JsonArray jsonArray = jsonParser.parse(this.plan).getAsJsonArray();
ArrayList<PlanJson> planJsonList = new ArrayList<PlanJson>();
for(JsonElement jsonElement:jsonArray)
{
System.out.println(jsonElement);
PlanJson planJson = gson.fromJson(jsonElement, PlanJson.class);
planJsonList.add(planJson);
}
I found it to be the most easiest to work out for my json structure.
You can use the jackson library. see: http://jackson.codehaus.org/
Here is an example from: http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
package com.mkyong.core;
import java.io.File;
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
public class JacksonExample {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
try {
// read from file, convert it to user class
User user = mapper.readValue(new File("c:\\user.json"), User.class);
// display to console
System.out.println(user);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Categories

Resources