DotNet.Highcharts and proper JSON - json

I have an inconsistent issue with the JSON sent to highcharts. Highcharts does not always reject the JSON, but when it does, updating the JSON by hand to a proper format consistently fixes it:
Exmaple DotNet.Hightcharts output:
series: [{ data: [284, 49, 100, 19], name: 'some name' }, { data: [230, 250, 219, 878], name: 'some name 2' }]
when fixed to included quotes it works:
"series": [{ "data": [284, 49, 100, 19], "name": "some name" }, { "data": [230, 250, 219, 878], "name": "some name 2" }]
Is there a way to get DotNet.Hightcharts to output this format?

Looking at the DotNet.Highcharts source code, it seems it uses its own JsonSerializer which does not quote property names, and there's no option to change this behavior nor swap out the serializer for another one altogether. They have made it straight forward to change the formatting in code though, so it looks like changing the following lines in: DotNet.Highcharts/JsonSerializer.cs should do what you need:
const string JSON_PROPERTY_WITH_VALUE_FORMAT = "{0}: {1}";
const string JSON_STRING_FORMAT = "'{0}'";
to become:
const string JSON_PROPERTY_WITH_VALUE_FORMAT = "{\"0\"}: {1}";
const string JSON_STRING_FORMAT = "\"{0}\"";
So I'd say you options are:
Compile your own version of DotNet.Highcharts using the source code with the above alterations.
Convince the project developers to include such changes in the next release.
Use an alternative library such as Highcharts.Net which does quote names by default.
Use no library at all and just render your data into a literal placed inside the hand-coded Highcharts javascript, using a stand alone Json formatter like Newtonsoft.Json.
Before any of the above though, it does sound a bit odd that this problem only emerges as more data is added. It's not just a case of apostrophes in your data breaking the format is it? They don't appear to be being escaped in the formatter.

Related

(electron-store) How can I use "patternProperties" when define schema

I am using library for my electron app called electron-store
It has a feature to validate config data.
I want the value to be stored in config file is a string. I can achive that by define schema like this:
const schema = {
1: {
type: 'string',
},
2: {
type: 'string',
},
3: {
type: 'string',
},
4: {
type: 'string',
},
};
const store = new Store({schema});
The data in my config.json file:
{
"1": "lorem epsum...",
"2": "epsum lorem...",
"3": "epsum epsum...",
"4": "lorem lorem..."
}
The problem is I have hundreds line of datas like that, so it would be great if I could just define:
const schema = {
[any_key_name]: {
type: 'string',
},
};
I think I can use "patternProperties" when defining schema to achive it but I don't know how. help me please.
It looks like you cannot do this with electron-store as you want.
The docs say the following:
You should define your schema as an object where each key is the name
of your data's property and each value is a JSON schema used to
validate that property.
https://github.com/sindresorhus/electron-store#schema
This means that the root "schema" is not a JSON Schema. Only the value of each KEY is a JSON Schema.
If you want to use dynamic names, I think you would need to nest it under a specific key name, and validate that as a single object, although this is probably not what you really want to do with a store.
Sorry, I'm not familiar with electron-store specifically.
If you COULD provide a full JSON Schema for the whole store...
You can use patternProperties.
If you don't need to check the key follows any specific regex, you can use additionalProperties, which would then cover all properties not checked by properties (if present).
LEt's look at the specification: https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.5.6
The value of "additionalProperties" MUST be a valid JSON Schema.
This keyword determines how child instances validate for objects,
and does not directly validate the immediate instance itself.
Validation with "additionalProperties" applies only to the child
values of instance names that do not match any names in "properties",
and do not match any regular expression in "patternProperties".
As a pure JSON Schema, you'd be looking at...
{
"additionalProperties": {
"type": "string"
}
}
You can easily test this using https://jsonschema.dev (link has an example for you)

Power App - response from Flow is not treated as json

I have a power app that wants to collect some data from a rest API, I am using Flow as this seems to be the recommended way.
I have a collection:
[
{id: 1,name: "test",lines: [
{id: 244,
StrategyId: 1,
TypeId: 0,
Weight: 10,
toWeight: 200
}
]
},
{id: 3,name: "test2",lines: [
{id: 262,
StrategyId: 3,
TypeId: 0,
Weight: 0,
toWeight: 200
}
]
}
]
When I enter this into a formula straight up, it works fine:
ClearCollect( CityPopulations, json...)
However, when I try to fetch the data from Flow it only returns a collection with one single entry that is the json data as string.
Set('CityPopulations','PowerApp->Sendmeamobilenotification'.Run());ClearCollect(NewTable, CityPopulations.testoutput);
In Microsoft flow I use PowerApps trigger and Respond to PowerApps.
Also note that there are no " on the propertynames in json structure, but this was the only way I could get Power Apps to actually accept typing in json manually. I have tried having the respons propper, as well as this way. I had to adjust the flow to remove the " around propertynames. Still same result.
This is how the table looks in collections:
This is how it looks when I am entering the data manually:
this is the direct output from :
{
"testoutput": "[{id:1,name:\"test\",lines:[{id:244,StrategyId:1,TypeId:0,fromWeight:10,toWeight:200}]},{id:2,name:\"tester\",lines:[{id:154,StrategyId:2,TypeId:0,fromWeight:10,toWeight:200}]}]"
}
The biggest difference is the escape characters added from flow.
This took me quite some time to solve so maybe will help others.
When you want to return an array (collection) form Flow to a Canvas App you need to use Response (Request), not Respond to PowerApps.
All the problems go away with that
Tip: Remember to provide a SCHEMA and to remove and re-add the flow in the canvas app
It looks like your Collecting a single column of Text from the API Response rather than collecting the entire response.
Try just using:
ClearCollect(colNewTable,'PowerApp->Sendmeamobilenotification'.Run())
If you want to set colNewTable as a variable, wrap it like:
Set(varNewTable,ClearCollect(colNewTable,'PowerApp->Sendmeamobilenotification'.Run())
Hope this helps!

Inserted Nested Item in Generated JSON in Groovy/Grails

I am using Grails 2.1 to render JSON as part of a RestFul API I created. The Domain class, based on a SqlServer table, looks like this:
String firstName
String lastName
String officialAddress1
String officalAddress2
String preferredAddress1
String preferredAddress2
(etc.). . .
Which returns JSON similar to this:
{
"firstName": "Joe",
"lastName": "Hill",
"officialAddress1": "1100 Wob Hill",
"officialAddress2": "Apt. # 3",
"preferredAddress1": "1100 Wobbly Lane.",
"preferredAddress2": "Apartment 3."
}
It is working fine but the client wants me to nest the results in this fashion:
{
"firstName": "Joe",
"lastName": "Hill",
preferredAddress {
"preferredAddress1": "1100 Wobbly Lane.",
"preferredAddress1": "Apartment 3."
},
officialAddress {
"officialAddress1": "1100 Wob Hill",
"officialAddress2": "Apt. # 3"
}
}
My question is since the domain class, and the database, are not structure in a way to return this type of nested result how can I easily change this in my returned JSON? Do I have to abandon my way of just regurgitating the JSON based on the database/domain object and do a custom converter of some kind?
i'm new to this stackoverflow thing and i hope i will not mess it but i think i know what you need. in your bootstrap.groovy file you find "def init = { servletContext -> " line
put in there something like this:
JSON.registerObjectMarshaller(YourDomainName) {
def returnArray = [:]
returnArray['firstName'] = it.firstName
returnArray['lastName'] = it.lastName
returnArray['preferredAddress'] = [it.preferredAddress1 ,it.preferredAddress2]
returnArray['officialAddress'] = [it.officialAddress1 ,it.officialAddress2]
return returnArray
}
now when you use the render with JSON as you did grails will look in bootstrap and
render the domain as you asked.
hope this helps
The posted answer was correct. I just wanted to add the slight change I made to get the exact results I needed:
Thanks! That did it. I originally that it would not work exactly how I needed it but I was wrong. I changed the syntax slightly to get the results I needed.
returnArray['preferredAddress'] = [address1: it.preferredAddress1?.trim(),
address2: it.preferredAddress2?.trim(),
address3: it.preferredAddress3?.trim(),
city: it.preferredCity,
state: it.preferredState,
postCode: it.preferredPostCode,
country: it.preferredCountry
]

How to return a Date value from JSON to Google Visualization API

is there a way to retrieve date value from JSON in Google Visualization API?
Here is the snipplet for playground please copy the code below into it
When you run the code you won't have anything in result. you should remove the quotes from the date value I marked with comment in order to retrieve result.
function drawVisualization() {
var JSONObject = {
cols:
[
{id: 'header1', label: 'Header1', type: 'string'},
{id: 'header2', label: 'Header2', type: 'date'}
],
rows:
[
{
c:
[
{v: 'Value1'},
{v: "new Date(2010, 3, 28)"} // <= This is the format I receive from WebService
]
},
{
c:
[
{v: 'Value2'},
{v: new Date(2010, 3, 28)} // <=This is the format Google API accepts
]
}
]
};
var data = new google.visualization.DataTable(JSONObject, 0.5);
visualization = new google.visualization.Table(document.getElementById('table'));
visualization.draw(data, {'allowHtml': true});
}
I just ran into this problem myself, so I thought I'd paste the answer from the google api documentation, located here http://code.google.com/apis/chart/interactive/docs/dev/implementing_data_source.html#jsondatatable
"JSON does not support JavaScript Date values (for example, "new Date(2008,1,28,0,31,26)"; the API implementation does. However, the API does now support a custom valid JSON representation of dates as a string in the following format: Date(year, month, day[,hour, minute, second[, millisecond]]) where everything after day is optional, and months are zero-based."
I was running into same problem and above solution did not work. After searching for hours I found following post and the solution in there worked.
https://groups.google.com/forum/#!msg/google-visualization-api/SCDuNjuo7xo/ofAOTVbZg7YJ
Do not include "new" in the json string so it will be just:
v:"Date(2009, 9, 28)"
I suppose that the quote is not at the correct place in your snippet "new Date(2010, 3, 28")
Write instead "new Date(2010, 3, 28)"
Json format does not accept javascript object so the server return a string.
JSON knows only numbers, boolean constants, string, null, vector and 'object' (much more a dictionnary).
I suppose that you have to perform an eval() of the returned string (do not forget to check inputs).
Another alternative is to use a Regex to extract the fields something like /new Date\((\d+),(\d+),(\d+)\)/ will work.

Proper way to deal with variations in JSON serialization

I have a web service that uses Python's SimpleJSON to serialize JSON, and a javascript/ client that uses Google's Visualization API. When I try to read in the JSON response using Google Data Table's Query method, I am getting a "invalid label" error.
I noticed that Google spreadsheet outputs JSON without quotes around the object keys. I tried reading in JSON without the quotes and that works. I was wondering what was the best way to get SimpleJSON output to be read into Google datable using
query = new google.visualization.Query("http://www.myuri.com/api/").
I could use a regex to remove the quotes, but that seems sloppy. The javascript JSON parsing libraries I've tried won't read in JSON syntax without quotes around the object keys.
Here's some good background reading re: quotes around object keys:
http://simonwillison.net/2006/Oct/11/json/.
Are you certain the Google API is expecting JSON? In my experience Google's APIs tend not to be massively broken in a manner you're describing -- it could be that they're actually expecting a different format that merely resembles JSON.
Further poking around reveals instructions for retrieving data in the format Google expects:
For example, to get the dataSourceUrl
from a Google Spreadsheet, do the
following:
In your spreadsheet, select the range of cells.
Select 'Insert' and then 'Gadget' from the menu.
Open the gadget's menu by clicking on the top-right selector.
Select menu option 'Get data source URL'.
I did this and opened the URL in my browser. The data it was returning was certainly not JSON:
google.visualization.Query.setResponse(
{requestId:'0',status:'ok',signature:'1464883469881501252',
table:{cols: [{id:'A',label:'',type:'t',pattern:''},
{id:'B',label:'',type:'t',pattern:''}],
rows: [[{v:'a'},{v:'h'}],[{v:'b'},{v:'i'}],[{v:'c'},{v:'j'}],[{v:'d'},{v:'k'}],[{v:'e'},{v:'l'}],[{v:'f'},{v:'m'}],[{v:'g'},{v:'n'}]]}});
It looks like the result is intended to be directly executed by the browser. Try modifying your code to do something like this:
# old
return simplejson.dumps ({"requestId": 1, "status": "ok", ...})
# new
json = simplejson.dumps ({"requestId": 1, "status": "ok", ...})
return "google.visualization.Query.setResponse(%r);" % json
The "invalid label" error is usually due to a blind eval() on the JSON string, resulting in property names being mistaken as labels (because they have the same syntax -- "foo:").
eval("{ foo: 42, bar: 43 }"); // Results in invalid label
The quick remedy is to make sure your JSON string has parenthesis enclosing the curly braces:
eval("({ foo: 42, bar: 43 })"); // Works
Try enclosing your JSON string in parenthesis to see if the "invalid label" error goes away.
As it turns out :mod:json would also choke at strings in single quotes. This will sort things out though:
Parse JavaScript object as JSON in python:
solution:
>>> from re import sub
>>> import json
>>> js = "{ a: 'a' }"
>>> json.loads(sub("'", '"', sub('\s(\w+):', r' "\1":', js)))
{u'a': u'a'}
Edit: (edge cases reviewed)
So it was brought up that the suggested solution would not cope with all cases and specifically with something like
e.g. {foo: "a sentence: right here!"} will get changed to {"foo": "a "sentence": right here!"}
– Jason S Apr 12 at 18:03
To resolve that we simply need to ensure that we are in fact working with a key and not simply a colon in a string so we do a little look behind magic to hint at a comma(,) or a curly brace({) presence to ensure we have it proper, like so:
colon in string:
>>> js = "{foo: 'a sentence: right here!'}"
>>> json.loads(sub("'", '"', sub('(?<={|,)\s*(\w+):', r' "\1":', js)))
{u'foo': u'a sentence: right here!'}
Which of course is the same as doing:
>>> js = "{foo: 'a sentence: right here!'}"
>>> json.loads(sub('(?<={|,)\s*(\w+):', r' "\1":', js).replace("'",'"'))
{u'foo': u'a sentence: right here!'}
But then I pointed out that this is not the only flaw because what about quotes:
If we are also concerned about escaped quotes we will have to be slightly more specific as to what constitutes a string. The first quote will follow either a curly brace({) a space(\s) or a colon(:) while the last matching quote will come before either a comma(,) or a closing curly brace(}) then we can consider everything in between as part of the same string, like so:
additional quotes in string:
>>> js = "{foo: 'a sentence: it\'s right here!'}"
>>> json.loads(
... sub("(?<=\s|{|:)'(.*?)'(?=,|})",
... r'"\1"',
... sub('(?<={|,)\s*(\w+):', r' "\1":', js))
... )
{u'foo': u"a sentence: it's right here!"}
Watch this space as more edge cases are revealed and solved. Can you spot another?
Or for something more complex perhaps, a real world example as returned by npm view:
From:
{ name: 'chuck',
description: 'Chuck Norris joke dispenser.',
'dist-tags': { latest: '0.0.3' },
versions: '0.0.3',
maintainers: 'qard ',
time: { '0.0.3': '2011-08-19T22:00:54.744Z' },
author: 'Stephen Belanger ',
repository:
{ type: 'git',
url: 'git://github.com/qard/chuck.git' },
version: '0.0.3',
dependencies: { 'coffee-script': '>= 1.1.1' },
keywords:
[ 'chuck',
'norris',
'jokes',
'funny',
'fun' ],
bin: { chuck: './bin/chuck' },
main: 'index',
engines: { node: '>= 0.4.1 < 0.5.0' },
devDependencies: {},
dist:
{ shasum: '3af700056794400218f99b7da1170a4343f355ec',
tarball: 'http://registry.npmjs.org/chuck/-/chuck-0.0.3.tgz' },
scripts: {},
directories: {},
optionalDependencies: {} }
To:
{u'author': u'Stephen Belanger ',
u'bin': {u'chuck': u'./bin/chuck'},
u'dependencies': {u'coffee-script': u'>= 1.1.1'},
u'description': u'Chuck Norris joke dispenser.',
u'devDependencies': {},
u'directories': {},
u'dist': {u'shasum': u'3af700056794400218f99b7da1170a4343f355ec',
u'tarball': u'http://registry.npmjs.org/chuck/-/chuck-0.0.3.tgz'},
u'dist-tags': {u'latest': u'0.0.3'},
u'engines': {u'node': u'>= 0.4.1 < 0.5.0'},
u'keywords': [u'chuck', u'norris', u'jokes', u'funny', u'fun'],
u'main': u'index',
u'maintainers': u'qard ',
u'name': u'chuck',
u'optionalDependencies': {},
u'repository': {u'type': u'git', u'url': u'git://github.com/qard/chuck.git'},
u'scripts': {},
u'time': {u'0.0.3': u'2011-08-19T22:00:54.744Z'},
u'version': u'0.0.3',
u'versions': u'0.0.3'}
Works for me =)
nJoy!