Getting SerializableException while saving data into isolated storage - windows-phone-8

I am working on windows phone 8 app. In which I need to call an api to get some response, that I am serializing and saving into local settings
While saving these data I am getting an exception of type 'System.Runtime.Serialization.SerializationException'.
My Code is,
string someData = responseDataDict["SomeData"].ToString();
if someData != null)
{
Dictionary<string, Object> someDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(someData);
Datastore.SaveData = stringDict;
}
public static Datastore
{
get
{
if (localSettings.Contains("SaveData"))
{
return (Dictionary<string, Object>)localSettings["SaveData];
else
return null;
}
}
set
{
localSettings["SaveData"] = value;
localSettings.Save();
}
}
}
The response from api is,
"MESSAGE": "Some Message",
"UI_MESSAGE": {
"LEFT": "OK",
"RIGHT": "CANCEL",
}
I think the problem is in "UI_MESSAGE",
The Exception is,
System.Runtime.Serialization.SerializationException: Type 'Newtonsoft.Json.Linq.JObject' with data contract name 'ArrayOfKeyValueOfstringJTokeneJCYCtcq:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
Please help me to resolve this issue, Thanks in advance

You can't (easily) serialize the data because the serializer doesn't know how to serialize Newtonsoft.Json.Linq.JObject types.
We could try to figure out how to get the serializer working with this type, which may or may not take lots of time, or we could stop and think for a bit...
You grab the response data in the line
string someData = responseDataDict["SomeData"].ToString();
What is someData? It's
{
"MESSAGE": "Some Message",
"UI_MESSAGE": {
"LEFT": "OK",
"RIGHT": "CANCEL",
}
That's a json string. A serialized javascript object. It's already bloody serialized.
Save that in localSettings.

Related

What might cause (JSON ERROR: no value for)?

I have written some code in Kotlin that should retrieve some data for a dictionary app using the JSON Request Object. I can see that the call is made successfully. The website receiving the call shows the data being sent back but I'm not getting anything back in the results object. Logcat is showing this error (E/JSONĀ ERROR: No value for results). I'm not sure where I'm going wrong in extracting the results. Can someone point me in the right direction?
val jsonObjectRequest = JsonObjectRequest(Request.Method.GET, url, null,
{ response ->
try {
val resultsObj = response.getJSONObject("results")
val result: JSONObject = response.getJSONObject("result")
val term = result.getString("term")
val definition = result.getString("definition")
val partOfSpeech = result.getString("partOfSpeech")
val example = result.getString("example")
} catch (ex: JSONException) {
Log.e("JSON ERROR", ex.message!!)
}
},
{ error: VolleyError? -> error?.printStackTrace() })
The JSON
{
"results": {
"result": {
"term": "consistent, uniform",
"definition": "the same throughout in structure or composition",
"partofspeech": "adj",
"example": "bituminous coal is often treated as a
consistent and homogeneous product"
}
}
}
Have you checked the json format? Json Formatter
Here with this code it is valid. You had his character end line in the wrong place.
{
"results":{
"result":{
"term":"consistent, uniform",
"definition":"the same throughout in structure or composition",
"partofspeech":"adj",
"example":"bituminous coal is often treated as a consistent and homogeneous product"
}
}
}

Handling Large JSON bodies in Salesforce

Is there was way to digest large JSON bodies like you would with say a spring-boot project #JsonIgnoreProperties(ignoreUnknown=true). Where you do not have to have a DTO in its entirety matching the JSON body? I recently hit some limits with this approach of 1:1(DTO:JSON) and I have not been successful in finding something that will allow me to ignore the massive JSON bodies(7MB and UP).
Thank you all for your input.
You could use JSON.deserialize(jsonString, apexType). Unlike JSON.deserializeStrict() this method just ignores unknown attributes instead of throwing an exception.
You could test it in developer console:
String jsonString = '{ "unknown1": "aaa", "unknown2": "bbb", "type": "xyz", "id": "12345" }';
Data data = (Data) JSON.deserialize(jsonString, Data.class); // No Exception
System.debug(data);
try {
Data data = (Data) JSON.deserializeStrict(jsonString, Data.class);
} catch(JSONException e) {
System.debug('Exception thrown'); // You'll see this.
}
class Data {
public String type;
public String id;
}
Anyway if you have to handle more than 7MB of data, you should use an async transaction: the heap size limit is 6MB for synchronous one. Governor Limits

ZonedDateTime Custom JSON Converter Grails 3.3.0

I am in the process of converting a really old Grails app to the latest version (3.3.0). Things have been a bit frustrating, but I'm pretty close to migrating everything except the JSON and XML marshallers which were previously registered in my BootStrap init.
The previous marshaller registering looked like this:
// register JSON marshallers at startup in all environments
MarshallerUtils.registerMarshallers()
This was defined like this:
class MarshallerUtils {
// Registers marshaller logic for various types that
// aren't supported out of the box or that we want to customize.
// These are used whenever the JSON or XML converters are called,
// e.g. return model as JSON
static registerMarshallers() {
final dateTimeFormatter = ISODateTimeFormat.dateTimeNoMillis()
final isoDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
// register marshalling logic for both XML and JSON converters
[XML, JSON].each { converter ->
// This overrides the marshaller from the joda time plugin to
// force all DateTime instances to use the UTC time zone
// and the ISO standard "yyyy-mm-ddThh:mm:ssZ" format
converter.registerObjectMarshaller(DateTime, 10) { DateTime it ->
return it == null ? null : it.toString(dateTimeFormatter.withZone(org.joda.time.DateTimeZone.UTC))
}
converter.registerObjectMarshaller(Date, 10) { Date it ->
return it == null ? null : isoDateFormat.format(it)
}
converter.registerObjectMarshaller(TIMESTAMP, 10) { TIMESTAMP it ->
return it == null ? null : isoDateFormat.format(it.dateValue())
}
}
}
}
During the migration, I ended up converting all instances of org.joda.time.DateTime to java.time.ZonedDateTime:
class MarshallerUtils {
// Registers marshaller logic for various types that
// aren't supported out of the box or that we want to customize.
// These are used whenever the JSON or XML converters are called,
// e.g. return model as JSON
static registerMarshallers() {
final dateTimeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME
final isoDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
// register marshalling logic for both XML and JSON converters
[XML, JSON].each { converter ->
// This overrides the marshaller from the java.time to
// force all DateTime instances to use the UTC time zone
// and the ISO standard "yyyy-mm-ddThh:mm:ssZ" format
converter.registerObjectMarshaller(ZonedDateTime, 10) { ZonedDateTime it ->
return it == null ? null : it.toString(dateTimeFormatter.withZone(ZoneId.of("UTC")))
}
converter.registerObjectMarshaller(Date, 10) { Date it ->
return it == null ? null : isoDateFormat.format(it)
}
converter.registerObjectMarshaller(TIMESTAMP, 10) { TIMESTAMP it ->
return it == null ? null : isoDateFormat.format(it.dateValue())
}
}
}
}
Unfortunately, after the upgrade to Grails 3.3.0, this marshaller registering doesn't seem to be used at all, no matter what I try to do.
I do know that there is a new "JSON Views" way of doing things, but this particular service has many endpoints, and I don't want to write custom converters and ".gson" templates for all of them, if everything is already in the format I need. I just need the responses to be in JSON and the dates to behave property (be formatted strings).
Instead, what I am finding (compared to the previous behavior, is that the properties which utilize ZonedDateTime are "exploded" in my JSON output. There is an insane amount of garbage date object information that is not needed, and it is not formatted as a simple string as I expect.
I have tried a few things (mostly per recommendations in the offical latest Grails documentation) ---
Custom Converters
Default Date Format
Adding configurations for grails views in application.yml:
views:
json:
generator:
dateFormat: "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
locale: "en/US"
timeZone: "GMT"
Creating this path under "src":
src/main/resources/META-INF/services/grails.plugin.json.builder.JsonGenerator$Converter
And adding a Converter to my domain class which is named in the file above^:
class MultibeamFileConverter implements JsonGenerator.Converter {
final DateTimeFormatter isoDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(ZoneId.of("UTC"));
#Override
boolean handles(Class<?> type) {
MultibeamFile.isAssignableFrom(type)
}
#Override
Object convert(Object value, String key) {
MultibeamFile multibeamFile = (MultibeamFile)value
multibeamFile.startTime.format(isoDateFormat)
multibeamFile.endTime.format(isoDateFormat)
return multibeamFile
}
}
In my controller, I have changed:
return multibeamCatalogService.findFiles(cmd, params)
To this (in order to get JSON output in the browser as before):
respond multibeamCatalogService.findFiles(cmd, params), formats: ['json', 'xml']
Unfortuantely, most permutations I can think to try of the above have resulted in errors such as "Could not resolve view". Otherwise, when I am getting a response, the major issue is that the date is not formatted as a string. This function was previously performed by the Marshaller.
I am getting pretty frustrated. Can someone please tell me how to format ZonedDateTime as a simple string (e.g. - "2009-06-21T00:00:00Z") in my JSON output instead of a giant object like this? Simply converting to java.util.Date causes the "Could not resolve view" error to show up again; consequently, that expects me to make a ".gson" view which never ends up showing the format I expect or is empty.
"startTime": {
"dayOfMonth": 26,
"dayOfWeek": {
"enumType": "java.time.DayOfWeek",
"name": "FRIDAY"
},
"dayOfYear": 207,
"hour": 0,
"minute": 0,
"month": {
"enumType": "java.time.Month",
"name": "JULY"
},
"monthValue": 7,
"nano": 0,
"offset": {
"id": "-06:00",
"rules": {
"fixedOffset": true,
"transitionRules": [],
"transitions": []
},
"totalSeconds": -21600
}, ... // AND SO ON FOR_EVAH
The simple answer is to format a ZonedDateTime object you call .format(DateTimeFormatter). It depends what format you want. You can specify your own or use some of the predefined ones in DateTimeFormatter.
I too though would love to know if there's an easy way to say "for every endpoint display it as json". The only way I've found so far is to have this in every controller class, which isn't too bad but seems silly. I'm using respond followed by a return in my controller methods.
static responseFormats = ['json'] // This is needed for grails to indicate what format to use for respond.
Though I still see the error logged, but rest api still appears to work, "Could not resolve view" for any endpoint I hit.

How to intercept map getProperty and list getAt?

I'm scraping external sources, mostly JSON. I'm using new JsonSlurper().parse(body) to parse them and I operate on them using constructs like def name = json.user[0].name. These being external, can change without notice, so I want to be able to detect this and log it somehow.
After reading a bit about the MOP I thought that I can change the appropriate methods of the maps and lists to log if the property is missing. I only want to do that the json object and on its properties recursively. The thing is, I don't know how to do that.
Or, is there a better way to accomplish all this?
[EDIT] For example if I get this JSON:
def json = '''{
"owners": [
{
"firstName": "John",
"lastName": "Smith"
},
{
"firstName": "Jane",
"lastName": "Smith"
}
]
}'''
def data = new groovy.json.JsonSlurper().parse(json.bytes)
assert data.owners[0].firstName == 'John'
However, if they change "owners" to "ownerInfo" the above access would throw NPE. What I want is intercept the access and do something (like log it in a special log, or whatever). I can also decide to throw a more specialized exception.
I don't want to catch NullPointerException, because it may be caused by some bug in my code instead of the changed data format. Besides, if they changed "firstName" to "givenName", but kept the "owners" name, I'd just get a null value, not NPE. Ideally I want to detect this case as well.
I also don't want to put a lot of if or evlis operators, if possible.
I actually managed to intercept that for maps:
data.getMetaClass().getProperty = {name -> println ">>> $name"; delegate.get(name)}
assert data.owners // this prints ">>> owners"
I still can't find out how to do that for the list:
def owners = data.owners
owners.getMetaClass().getAt(o -> println "]]] $o"; delegate.getAt(o)}
assert owners[0] // this doesn't print anything
Try this
owners.getMetaClass().getAt = { Integer o -> println "]]] $o"; delegate.get(o)}
I'm only guessing that it got lost because of multiple getAt() methods, so you have to define type. I also delegated to ArrayList's Java get() method since getAt() resulted in recursive calls.
If you want to more control over all methods calls, you could always do this
owners.getMetaClass().invokeMethod = { String methodName, Object[] args ->
if (methodName == "getAt") {
println "]]] $args"
}
return ArrayList.getMetaClass().getMetaMethod(methodName, args).invoke(delegate, args)
}
The short answer is that you can't do this with the given example. The reason is that the owners object is a java.util.ArrayList, and you are calling the get(int index) method on it. The metaClass object is specific to Groovy, and if you have a Java object making a method call to a Java method, it will have no knowledge of the metaClass. Here's a somewhat related question.
The good news is that there is and option, although I'm not sure if it works for your use case. You can create a Groovy wrapper object for this list, so that you can capture method calls.
For example, you could change your code from this
def owners = data.owners
to this
def owners = new GroovyList(data.owners)
and then create this new class
class GroovyList {
private List list
public GroovyList(List list) {
this.list = list
}
public Object getAt(int index) {
println "]]] $index"
list.getAt(index)
}
}
Now when you call
owners[0]
you'll get the output
]]] 0
[firstName:John, lastName:Smith]

Grails: Parsing through JSON String using JSONArray/JSONObject

I have the below JSON string coming in as a request parameter into my grails controller.
{
"loginName":"user1",
"timesheetList":
[
{
"periodBegin":"2014/10/12",
"periodEnd":"2014/10/18",
"timesheetRows":[
{
"task":"Cleaning",
"description":"cleaning description",
"paycode":"payCode1"
},
{
"task":"painting",
"activityDescription":"painting description",
"paycode":"payCode2"
}
]
}
],
"overallStatus":"SUCCESS"
}
As you can see, the timesheetList might have multiple elements in it. In this ( above ) case, we have only one. So, I expect it to behave like an Array/List.
Then I had the below code to parse through it:
String saveJSON // This holds the above JSON string.
def jsonObject = grails.converters.JSON.parse(saveJSON) // No problem here. Returns a JSONObject. I checked the class type.
def jsonArray = jsonArray.timesheetList // No problem here. Returns a JSONArray. I checked the class type.
println "*** Size of jsonArray1: " + jsonArray1.size() // Returns size 1. It seemed fine as the above JSON string had only one timesheet in timesheetList
def timesheet1 = jsonArray[1] // This throws the JSONException, JSONArray[1] not found. I tried jsonArray.getJSONObject(1) and that throws the same exception.
Basically, I am looking to seamlessly iterate through the JSON string now. Any help?
1st off to simplify your code, use request.JSON. Then request.JSON.list[ 0 ] should be working