Are Json values type specific - json

I'm trying to understand what is going on when I query data from a database and provide it to JSON and then push it to a GUI, in regards to what and when is converting to a string.
If I make a call to a database and provide this data as JSON to the front end, my JSON may look like
MyData{ [["Name": "Anna", "Age": 50],["Name": "Bob", "Age": 40 ]};
Visually it appears as if the value for Name is a string (as it's in quote marks) and the value for Age is an integer (as of no quote marks).
My 2 questions are
Is my understanding that the value for Name is a string and the value of Age is an integer or does JavaScript convert/cast behind the scenes?
How would I specify the type DateTime. According to The "right" JSON date format I actually just ensure the format is correct but ultimately it's a string.

Is my understanding that the value for Name is a string and the value of Age is an integer...?
Almost. It's a number, which may or may not be an integer. For instance, 10.5 is a number, but not an integer.
...or does JavaScript convert/cast behind the scenes?
JavaScript and JSON are different things. JSON defines that the number will be represented by a specific format of digits, . and possibly the e or E character. Whatever environment you're parsing the JSON in will map that number to an appropriate data type in its environment. In JavaScript's case, it's an IEEE-754 double-precision binary floating point number. So in that sense, JavaScript may cast/convert the number, if the JSON defines a number that can't be accurately represented in IEEE-754, such as 9007199254740999 (which becomes the number 9007199254741000 because IEEE-754 only has ~15 digits of decimal precision).
How would I specify the type DateTime. According to The "right" JSON date format I actually just ensure the format is correct but ultimately it's a string.
JSON has a fixed number of types: object, array, string, number, boolean, null. You can't add your own. So what you do is encode any type meta-data you want into either the key or value, or use an object with separate properties for type and value, and enforce that agreement at both ends.
An example of doing this is the common format for encoding date/time values: "/Date(1465198261547)/". As far as the JSON parser is concerned, that's just a string, but many projects use it as an indicator that it's actually a date, with the number in the parens being the number of milliseconds since The Epoch (Jan 1 1970 at midnight, GMT).
Two concepts related to this are a replacer and a reviver: When converting a native structure to JSON, the JSON serializer you're using may support a replacer which lets you replace a value during the serialization with another value. The JSON parser you're using may support a reviver that lets you handle the process in the other direction.
For example, if you were writing JavaScript code and wanted to preserve Dates across a JSON layer, you might do this when serializing to JSON:
var obj = {
foo: "bar",
answer: 42,
date: new Date()
};
var json = JSON.stringify(obj, function(key, value) {
var rawValue = this[key];
if (rawValue instanceof Date) {
// It's a date, convert it to our special format
return "/Date(" + rawValue.getTime() + ")/";
}
return value;
});
console.log(json);
That uses the "replacer" parameter of JSON.stringify to encode dates in the way I described earlier.
Then you might do this when parsing that JSON:
var json = '{"foo":"bar","answer":42,"date":"/Date(1465199095286)/"}';
var rexIsDate = /^\/Date\((-?\d+)\)\/$/;
var obj = JSON.parse(json, function(key, value) {
var match;
if (typeof value == "string" && (match = rexIsDate.exec(value)) != null) {
// It's a date, create a Date instance using the number
return new Date(+match[1]);
}
return value;
});
console.log(obj);
That uses a "reviver" to detect keys in the special format and convert them back into Date instances.

The specific format of a JSON string can be described by JSON Schema, as described here; in particular, date-time apparently is a type already defined in JSON Schema.

Related

Parsing Vector to Array String

I'm new to Rust.
I try to write a websocket client.
This is my format message:
"[integer, "string", object]"
Is there away to store all value in Vector something like:
let msg: Vec<interface> = vec![123, "event", AnyObject{}];
How to convert it into string and vice versa.
Thanks in advance
Conceptually speaking you want to use an enum. The type of enums used in rust are called tagged unions. Essentially you can think of them as enums which can hold data.
enum Interface {
Int(i32),
String(&'static str),
Object(AnyObject),
// etc
}
// You can then create a vec of different enum variants
let msg: Vec<Interface> = vec![Interface::Int(123), Interface::String("event"), Interface::Object(AnyObject{})];
Assuming you are referring to JSON, then the recommended solution is to use serde with serde_json. serde_json provides a Value enum you can use to represent JSON data in an unknown layout.
// Copied from serde_json docs
enum Value {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<Value>),
Object(Map<String, Value>),
}
However, you don't need to use Value directly (unless you want to) since serde_json provides a macro to make this easier by letting you format your code like JSON.
use serde_json::{json, Value};
let msg: Value = json!([123, "event", {}]);
// You can then serialize a Value into JSON format
println!("{:?}", msg.to_string());
// Output: "[123,\"event\",{}]"
I recommend reading through the overview since they have a bunch of convenient ways for working with JSON.

Ballerina json datetime value

i have to index documents to elasticsearch to an index which has a date field mapping and i'm trying to build a json with this date value, but ballerina says this seems not possible.
I thought about storing this date value into an xml and after that to convert it to a json but xml has the same problem (i thought this might be a trick...).
I tried to store it into a string and after that to extract the json payload from that string but it gives me this error:
error: {ballerina/io}GenericError message=unrecognized token 'date=time=1591128342000'
I thought about dealing with this string to date conversion from inside elasticsearch but i would like to keep this scenario as the last one. I don't like it, beacause i have to do some queries based on timestamp after and storing date as a string would give me additional problems
So is there any way to trick ballerina in order to achive this json containing a date value ?
-----here is snapshot of the code giving me the error-----
It says:
incompatible types: expected 'json', found 'ballerina/time:Time'
JSON is a text format that is completely language independent (see e.g. json.org).
time:Time is a Ballerina language specific type JSON knows nothing about. Because there is no implicit conversion (for a good reason) one have to provide the conversion.
In this case you most likely want to convert time:Time to a ISO 8601 string presentation with time:toString.
The following code (Ballerina 1.2):
import ballerina/io;
import ballerina/time;
public function main() {
var btime = time:currentTime();
var j = <json> {
time: time:toString(btime)
};
io:println(j.toJsonString());
}
Correctly prints:
{"time":"2020-06-03T08:39:07.897+03:00"}
Maryam Ziyad has written a good introduction to Ballerina's JSON support.
The following code is updated for Ballerina Swan Lake Update 1 (2201.1.0) to show how to convert a Ballerina UTC time (time:Utc) to JSON representation. Note that it's also possible to use localized time (time:Civil) but that is no different from time to JSON conversion point of view.
One can read more about Ballerina time handling from the documentation of time module.
import ballerina/io;
import ballerina/time;
public function main() {
time:Utc now = time:utcNow(3);
json j = {
time: time:utcToString(now)
};
io:println(j.toJsonString());
}
That correctly prints:
{"time":"2022-07-20T06:03:46.078Z"}

Hamcrest Contains Matcher

So my problem is presenting as a type-matching of sorts; I have code that queries a database, and returns an array of string type. When I attempt to validate against my JSON message returned from a web service, one of the values is a primitive integer (without the double-quotes), and the validation is failing, as it is stating: Expected: iterable containing {"1", "1", "1", "1", "1"}Actual: [1, 1, 1, 1, 1]I'm using the contains matcher to validate a ListArray of values against many returned by the query. My assumption is that the Actual is being evaluated as an integer, but the values to validate against (Expected) are String. I've been racking my brain attempting the HasToString or hasItem matchers but I think that would just parse toString if the target is a single value.I guess my ultimate question is, is there a way to force Hamcrest to evaluate the JSON data as a String, or implicitly/explicitly cast the Expected to the evaluated type?Thanks in advance.
So, I acutally think I figured this one out; what I ended up doing was performing a toString(). on the extracted ArrayList of objects, which gave me string values; code example below:
ArrayList<String> myObj = response.path(jsonField);
String[] myObjStr = new String[myObj.size()];
int x = 0;
for (Object obj : myObj){
myObjStr[x] = obj.toString();
x++;
}
From there, I was able to compare the resulting arrays; Now if only I could figure out how to get rid of pesky angle brackets for nested elements...

JSON decoding in PERL - Maintaining the original data type

I am writing a simple perl script to read JSON from a file and insert into MongoDB. But I am facing issues with json decoding.
All non-string values in my original json are getting converted to object type after decode_json.
Input JSON(only part of it since it's original is huge) -
{
"_id": 2006010100000801089,
"show_image" : false,
"event" : "publish",
"publish_date" :1136091600,
"data_version" : 1
}
JSON that gets inserted to MongoDB -
{
"_id": NumberLong("2006010100000801089"),
"show_image" : BinData(0,"MA=="),
"event" : "publish",
"publish_date" :NumberLong(1136091600),
"data_version" : NumberLong(1)
}
I am providing the custom _id for the documents, which I want to get converted to NumberLong type. That is working as expected as you can see from the JSON above. But notice how other non-string values for show_image, publish_date and data_version got converted to it's object representation.
Is there any way I can retain the original type for these values?
Perl code snipper that does the insert -
use MongoDB;
use MongoDB::OID;
use JSON;
use JSON::XS
while(my $record = <$source_file>) {
my $record_decoded = decode_json($record);
$db_collection->insert($record_decoded);
}
Perl version used v5.18.2.
I looked up JSON::XS docs but couldn't find a way to do this. Any help is appreciated. Thanks in advance!
I am very new to perl. Sorry if this is a trivial question.
I am providing the custom _id for the documents, which I want to get converted to NumberLong type. That is working as expected as you can see from the JSON above. But notice how other non-string values for show_image, publish_date and data_version got converted to it's object representation.
From your example all of the data types are actually matching aside from the boolean value for show_image which is currently being converted to binary data.
It is expected that numeric types are displayed as NumberLong or NumberInt when queried from the mongo shell. The mongo shell uses JavaScript, which only has a single numeric type of Number (64-bit floating point). Shell helpers like NumberLong() and NumberInt() are used to represent values in MongoDB's BSON data types that do not have a native JavaScript equivalent.
Referring to my sample JSON, I want value of show_image to be inserted as false instead of BinData(0,"MA==") and publish_date to be inserted as 1136091600 instead of NumberLong(1136091600)
While it's OK to insert publish_date as a Unixtime if that suits your use case, you may find it more useful to use MongoDB's Date type instead. There are convenience methods for querying dates including Date Aggregation Operators. FYI, date fields will be displayed in the mongo shell with an ISODate() wrapper.
The boolean value for show_image definitely needs an assist, though.
If you use Data::Dumper to inspect the result from decode_json(), you will see that the show_image field is a blessed object:
'show_image' => bless( do{\(my $o = 0)}, 'JSON::PP::Boolean' )
In order to get the expected boolean value in MongoDB, the recommended approach in the MongoDB module docs is to use the boolean module (see: MongoDB::DataTypes).
I couldn't find an obvious built-in option for JSON or JSON::XS to support serialising booleans to something other than the JSON emulated boolean class, but one solution would be to use the Data::Clean::Base module which is part of the Data::Clean::JSON distribution.
Sample snippet (excluding the MongoDB set up):
use Data::Clean::Base;
use boolean;
my $cleanser = Data::Clean::Base->new(
'JSON::XS::Boolean' => ['call_func', 'boolean::boolean'],
'JSON::PP::Boolean' => ['call_func', 'boolean::boolean']
);
while (my $record = <$source_file>) {
my $record_decoded = decode_json($record);
$cleanser->clean_in_place($record_decoded);
$db_collection->insert($record_decoded);
}
Sample record as saved in MongoDB 3.0.2:
{
"_id": NumberLong("2006010100000801089"),
"event": "publish",
"data_version": NumberLong("1"),
"show_image": false,
"publish_date": NumberLong("1136091600")
}
JSON data contains only (double-precision) numbers, strings, and the special values true, false, and null. They can be arranged in arrays or "objects" (hashes).
The MongoDB engine is converting these basic types into something more complex, but the original values are available in the hash referred to by $record_decoded, like so
$record_decoded->{_id}
$record_decoded->{show_image}
$record_decoded->{event}
$record_decoded->{publish_date}
$record_decoded->{data_version}
Is that what you wanted?
The object serialization documentation (particularly allow_tags) in JSON::XS may do something like what you want. Note, though, that this is not a standard JSON feature and will only work with JSON::XS.

Replacing data fields with code in JSON.stringify?

So you can replace a property with a number, string, array, or object in JSON.stringify, like so:
var myObj = {
'allstar': aFunction;
}
function myReplacer(key, value) {
if(key === 'allstar') {
return 'newFunction()';
}
}
JSON.stringify(myObj, myReplacer); //returns '{"allstar": "newFunction()"}'
But can you change it so that it instead returns '{"allstar": newFunction()}' (without the quotes around newFunction)?
I assume typeof aFunction == "function"? If so, even JSON.stringify(myObj) will not do what you want it to do, but return '{}' i.e. an object without properties, because functions are not supported in JSON.
Your desired result is not even valid JSON. newFunction() without quotes is not a supported value (string, number, array, object, boolean, null).
Edit: you could try to return newfunction.toString() in your replacer, which should deliver your function's source as string. When converting the JSON back, you then must eval() this string to get the actual function.
#derpirscher provided a very good answer that will probably get more upvotes than this one, but this is my preferred answer:
Based on derpirscher's answer I decided it would be easier to make my own version of JSON.stringify that allows you to replace properties with your own source code, and changed the name of the module so that there is no naming conflict with JSON.
It's on my github account:
https://github.com/johnlarson/xerxes