How to avoid 'null' strings when binding JSON data on client side - javascript

Is it possible to avoid having 'NULL' stings on the client when binding JSON data to HTML UI?
I'm using ASP.NET MVC + jQuery + jTemplates. Data is coming from linq-to-sql classes and these classes have quite a lot of nullable properties. When such properties get serialized and transferred back to client I end up with such JSON:
[{"Id":1,"SuitId":1,"TypeId":null,"Type":null,"CourtId":null,"Court":null}]
Whey I bind this data to HTML I have a lot of 'NULL' strings. I've tried both manual binding and JavaScript templating engines (jTemplate). Results are the same.
Currently I'm dealing with this issue by 'coalescing' the null values as follows:
$('#Elem').val(someVar||'');
But I don't want to do it manually.
Please advice if I:
Can automatically translate nullable properties to empty strings by either tweaking the serialization process or maybe choosing the 3rd party JSON serializer over .NET JSON serializer.
Can do anything on client side, such as working around this with either jQuery or templating engines.
Thank you.

You can modify jtemplate to return an empty string instead of null by modifying the follow line of code in jquery.jtemplate.js.
First find this function
TemplateUtils.cloneData = function(d, filter, f_escapeString) {
The very next block of code is an if statement
if (d == null) {
return d;
}
Modify that to
if (d == null) {
return "";
}
And that should do it

You could set up custom serialization (see
How to implement custom JSON serialization from ASP.NET web service? )
You could also make your own version of val that converts null to an empty string. However, I think that the method you are currently using is probably better anyway - the generic methods could add a lot of complexity and possibly hidden bugs.

I tend to ask myself at what point is the data incorrect? Is is incorrect to say the TypeId is null (unknown, not assigned) when it should specifically be assigned '' (empty string)?
In this case I would guess not, what is incorrect it the way the presentation displays "null", you want simply an empty textbox or some such thing. In this case its the presentations problem to convert the data to a view that is acceptable, thats its job. Hence your use of "coalescence" seems correct to me.
Of course thats perhaps an overly strict interpretation and may not be as pragmatic as you would like. In the long run though (I mean over the code's lifetime) it usually best to keep things as correct as they can pratically be.

For jTemplates only, this is what I did:
{#if $T.mylist.nullableProperty != null}{$T.myList.nullableProperty}{#/if}

Related

Having troubles with javascript types

So I am using a plugin for tags in a form and it works well but I am having troubles with the suggestions.
You can have an autocompleter by specifying an attribute
suggestions: ['Black','White','Red','Blue','Green','Orange']
Thing is, I have to make a call to a servlet to find the keywords to put in there, so I end up with a String that I try to pass to the attribute.
var dataFromServlet = "'Black','White','Red','Blue','Green','Orange'";
suggestions: [dataFromServlet]
Thing is, now the completer assumes the ENTIRE String is one element.
I have been at this for hours and I can't for the life of me figure out how to solve this seemingly very simple problem. I have tried using arrays, passing JSON from the servlet instead and parsing it, splitting the string and using a loop to rebuild it differently, nothing works. This is driving me crazy, I feel like I'm missing something very obvious.
The plugin documentation does suggest a different method for fetching suggestions via ajax calls, but it ends up calling the ajax method on every single keypress and it lags the whole thing out.
The best solution, have the backend return a proper JSON object. That way you do not have to worry about your hacky solution breaking because of the data in the string.
If for some problem out of your control you can not make a change to the back end, you can convert to an array by reformatting the string and using JSON.parse
var dataFromServlet = "'Black','White','Red','Blue','Green','Orange'";
var obj = {
suggestions: JSON.parse("[" + dataFromServlet.replace(/'/g, '"') + "]")
};
console.log(obj.suggestions);
Again, this solution is a bandaid, the correct solution is make the back end servlet return proper JSON formatted data.

How to handle empty Objects in API responses before rendering to page?

I'm currently using Petfinder's api to build a side project in order to learn Node.
The problem is that Petfinder's api will sometimes return an empty object for specific fields that I might want to display on the page. So far, I've been checking against the existence of a non-empty object like so on point of generating the HTML:
<img class="pet-image" src="${Object.keys(pet.media).length !== 0 ? pet.media.photos.photo[3].$t : ""}">
But this code is quite ugly and I know that it shouldn't be done here. Plus, it would get quite cumbersome to always have to do this for non-required fields from the API response. What are some strategies on how to handle this?
What are some strategies on how to handle this?
There are tools like _.get (from lodash) that let you get an object's property at a path and automate this - however generally it is not a great approach to have objects whose type you are not sure of in your code.
The most common and my favorite strategy would be to convert the object to a form you are familiar with at the call site (when the request arrives):
const someWeirdAPI = await fetch('./endpoint').then(x => x.json());
const result = {
cake: someWeirdAPI.cake || "Default Cake",
pets: someWeirdAPI.pets || [] // or some other default
// ... etc
};
That way, you know that when you got the object inside your code it is always valid - you can also add properties when you translate between the API data transfer object and your domain layer objects (your logic).

Are single-lettered word models supported in EmberJS?

I cannot really pinpoint whether the issue is with Ember or Ember data, or if it's even an issue, but here's what happens:
Let's say you've got your model called tell_me_a_story. This will be the name that your JSON should provide, should you be using ActiveModelAdapter.
Regardless, when Ember or Ember Data process it internally, it'll camelize it and it becomes tellMeAStory, correctly indicating that "A" and "Story" are two separate words.
However, when internally it is decamelized to lookup for the model, the decamelize function will convert it into tell_me_astory.
This final behavior seems flawed to me, but when looking at the tests that derived this behavior, it is actually intended to manage acronyms in that fashion. (Compare the following example with the "innerHtml" that I would expect for camel casing multi-letter acronyms.)
QUnit.test("converts a camelized string into all lower case separated by underscores.", function() {
deepEqual(decamelize('innerHTML'), 'inner_html');
if (Ember.EXTEND_PROTOTYPES) {
deepEqual('innerHTML'.decamelize(), 'inner_html');
}
});
(Source in Ember Runtime)
So, which is the correct way to use single-letter words in models with Ember? Are they even supported?
Here's an example of what I'm trying to do:
// this comes from a separate data source, e.g. REST APIs
var myModelName = 'tell_me_a_story';
// this line will throw if the model file is named "tell-me-a-story"
if (!store.getById(myModelName, 1)) {
// this line will throw if the model file is named "tell-me-astory"
store.pushPayload(myModelName, myObject);
}
You can override the stores _normalizeTypeKey then alter the camelCase behaviour to become what you want (e.g. dasherized or just fix this one case).
You can also override the serialisers typeForRoot when going the other way - this lets you tell ember what the model key is (e.g. tellMeAStory) for a particular key in your data (e.g. tell_me_a_story).
It appears there is work underway to make everything work like the container does (which is dasherized)

Return JSON with object model or JSON with parsed view

I'm creating website with lots of AJAX logic. I started to wondering should I return JSON with object model (because I have to make some requests and then replace/insert some html nodes in response) like:
{ 'Author' : 'Name#Surname', 'Email': 'some#email', 'listOfSomething' = [...], ...} //very advanced JSON
and then use some js template engine to parse my object and insert in the right place in the DOM
OR
return JSON with parsed razor template so something like:
{listOfSomething: [{id:0, parsedView:ASP.NET.ParseViewWithModel(MyModel[0])},{id:1, parsedView:ASP.NET.ParseViewWithModel(MyModel[1])}, ... ]}
the pros of second choice is that it will require much less logic but. Which approach should be use and when? Is the second approach may be good solution?
If what is being returned is only used in one place, then I would say option two is a good approach since you can tailor the HTML specifically for where it is going to be used and all you have to do is simply inject it into the DOM.
Otherwise, if what the AJAX returns is used in multiple places, then I would stick to returning JSON and let each client do what it needs with the raw data.
Also, if third-party developers are using it, then JSON is definitely the way to go.

database id number very big in GAE Launcher?

I'm since las update of GAE Launcher, it creates ID on datastore too big. Like 5330010158992982016, thats a problem to me, because on Javascript these numbers are rounded.
For example, on JS
> a = 533001015899298254645
> 533001015899298270000
an reading a JSON like [{"pk": 5330010158992982016, "model": " .... }],
$.getJSON(' ...
$.each(data, function(i,item){ ...
item['pk'] = 533001015899298270000 instead of 533001015899298254645
}
}
I'm not sure if I'll have the same problem on GAE servers. Any idea to limit ID size?
I'm using Django, but I'm having the same problem with Django and Google Models.
Update:
I found a solution that doesn't force you to change all javascript code of the project. In my case a lot. Like everybody says the best thing is to use de PK (or ID) as a string. But I as using django serializer and in my version and with JSON, the PK is set as a number. The easy solution is change this on the serializer class ( or create a new serializer wich extends original and change this ):
def end_object(self, obj):
self.objects.append({
"model" : smart_unicode(obj._meta),
"pk" : smart_unicode(obj._get_pk_val(), strings_only=**False**),
"fields" : self._current
})
self._current = None
Put strings_only to False. It makes the pk on the JSON goes with quotes. All the javascript code works without changes.
The question is... is there any other way to force django serializer to put it as String?
There is no way to read/store this number accurately in JavaScript, since in JavaScript numbers are actually double precision floats and the maximum is 900,719,925,4740,992.
You could
return the ids as string instead or
start the dev_appserver.py with an argument: --auto_id_policy=sequential
If for some strange reason Lipi's answer didn't cover you you can try another
approach which will be to cast all values to strings. So you would have
[{"pk": "5330010158992982016", "model": " .... "}],
I see you are using an Ajax call which probably means you won't need the following part but
For you Django variables instead of {{my_id}} you can make it a string like '{{my_id}}' if you are creating your JavaScript variables on render time.
The AppEngine team is aware of the issue and it will be resolved before the roll the update in production.

Categories