A TypeScript application sends a Uint8Array object through an HTTP POST request to a Scala Play application.
How to convert the Uint8Array object into a Scala object in the Play application?
For example, the TypeScript code sends the following object:
{stuff: new Uint8Array([0, 1, 2])}
Inside the Scala Play controller:
case class StuffData(stuff: List[Byte])
implicit val reads: Reads[StuffData] = Json.reads[StuffData]
def processStuff = Action.async(parse.json[StuffData]) { request =>
val stuffData = request.body
println(stuffData)
}
This does not work... the error message from Play is:
For request 'POST /send-stuff'
[Json validation error List((obj.key,List(JsonValidationError(List(error.expected.jsarray),WrappedArray()))))]
By default, Unit8Array is encoded in JSON as {"0":1,"1":2,"2":3,"3":4}, so you can decode it in Scala as a Map or write your custom reader, that can translate this object into an array type. Or you could make changes from the other side, instead of using Uint8Array you can use an array or a custom stringify function that makes expected JSON.
In my opinion, the easiest one is writing the custom reader. Custom reader example:
implicit val stuffReader = new Reads[StuffData] {
def reads(js: JsValue): JsResult[StuffData] = {
JsSuccess(StuffData(
(js \ "stuff").as[Map[String, Int]].toList.map(_._2)
))
}
}
Related
Perhaps a simple question but I am still new to JS / nodeJS.
I have a script that is doing some basic string matching (dict.js), and I am trying to access a JSON formatted object from another file (words.json) to iterate through.
The directory structure looks like:
scratch
- algorithms
- dict.js
- utilities
- words.json
The contents of the files are:
words.json
{"a": 1,"aa": 1,"aaa": 1,"aah": 1,"aahed": 1,"aahing": 1,"aahs": 1,"aal": 1}
dict.js
decode (password) {
const jsonData = require('../utilities/words.json');
myObj = JSON.parse(jsonData);
for (const x in myObj) {
console.log(x)
// compare password against item in words.json
}
console.log(Object.keys(myObj).length)
return "stub";
}
I am getting an error in developer tools when I create a block (this is the backend to a block in Scratch) that uses this Decode function.
Uncaught SyntaxError: Unexpected token o in JSON at position 1
Thanks
In nodejs environment you can directly import json file data without parsing it. For exaple:
const myObj = require('../utilities/words');
This gives you the data in your json file as a ready-to-go object.
In your case, you are trying to parse json object with JSON.parse() which expects stringified json. So just remove the part JSON.parse(jsonData);
I'm sending an ack to a received message in Node.js server and I want to echo the messageId back to the client. Currently I'm parsing the messageId from a buffer to string and building the ack from the string. Parsing the id to string and back is unnecessary but I'm unable to build the ack directly with the stuct buffer.
This is how it works when messageid is passed in as a string.
function createAck(messageId) {
let builder = new flatbuffers.Builder;
const request = MyServer.MessageAck;
request.startMessageAck(builder);
request.addMessgeId(builder, createUUID(builder, messageId));
const requestMessage = request.endMessageAck(builder);
return builder.finish(requestMessage);
}
function createUUID(builder, messageId) {
let uuidBytes = new Uint8Array(uuidParse.parse(messageId));
let dataview = new DataView(uuidBytes.buffer);
return MyServer.UUID.createUUID(builder,
flatbuffers.Long.create(dataview.getInt32(0, true), dataview.getInt32(4, true)),
flatbuffers.Long.create(dataview.getInt32(8, true), dataview.getInt32(12, true)));
}
I would like to pass in the messageId as a buffer directly taken from the message with
request.addMessgeId(builder, messageId);
But I'm getting an error: 'FlatBuffers: struct must be serialized inline.'
Here is the struct:
struct UUID {
low_bytes: ulong;
high_bytes: ulong;
}
The error refers to the fact that structs must be stored in-line, i.e. their bytes must be written to the buffer in between startMessageAck and endMessageAck. You can't refer to a struct stored elsewhere.
You should be able to copy the existing struct without using the intermediate Uint8Array and DataView however, something along the lines of (not tested):
request.addMessgeId(builder, MyServer.UUID.createUUID(builder,
messageId.low_bytes(), messageId.high_bytes());
Assuming messageId is a reference to an incoming UUID struct, can't tell from your code.
Even better would be if you could copy the struct using the JS equivalent of C memcpy, but that would require some hackery directly on the ByteBuffer in the builder that the current API doesn't directly support, so is probably not worth it for just 2 fields.
I need to make HTML fill itself with content from JSON file using Mustache or Handlebars.
I created two simple HTML templates for testing (using Handlebars) and filled them with content from an external JavaScript file. http://codepen.io/MaxVelichkin/pen/qNgxpB
Now I need content to lay initially in a JSON file.
I ran into two problems, but they both lie at the heart of solutions of the same main problem - creating a link between the content in the JSON file and HTML, so I decided to ask them in the same question.
How can I connect JSON and HTML? As far as I know there is a way, using AJAX, and there's a way that uses a server. AJAX is a new language for me, so I would be grateful for an explanation of how can I do it, using local HTTP server, that I created using Node.JS.
What should be the syntax in a JSON file? The script in the JSON file must be the same, as a script in JavaScript file, but then it should be processed with the help of JSON.parse function, is that correct? Or syntax in JSON file should be different?
For example, if we consider my example (link above), the code for the first template in the JSON file must be the same as in the JavaScript file, but before the last line document.getElementById('quoteData').innerHTML += quoteData;, I have to write the following line var contentJS = JSON.parse(quoteData);, and then change the name of the variable in the last line, so it will be: document.getElementById('quoteData').innerHTML += contentJS;, Is it right?
Try this:
HTML:
<!-- template-1 -->
<div id="testData"></div>
<script id="date-template" type="text/x-handlebars-template">
Date:<span> <b>{{date}}</b> </span> <br/> Time: <span><b>{{time}}</b></span>
</script>
JS:
function sendGet(callback) {
/* create an AJAX request using XMLHttpRequest*/
var xhr = new XMLHttpRequest();
/*reference json url taken from: http://www.jsontest.com/*/
/* Specify the type of request by using XMLHttpRequest "open",
here 'GET'(argument one) refers to request type
"http://date.jsontest.com/" (argument two) refers to JSON file location*/
xhr.open('GET', "http://date.jsontest.com/");
/*Using onload event handler you can check status of your request*/
xhr.onload = function () {
if (xhr.status === 200) {
callback(JSON.parse(xhr.responseText));
} else {
alert(xhr.statusText);
}
};
/*Using onerror event handler you can check error state, if your request failed to get the data*/
xhr.onerror = function () {
alert("Network Error");
};
/*send the request to server*/
xhr.send();
}
//For template-1
var dateTemplate = document.getElementById("date-template").innerHTML;
var template = Handlebars.compile(dateTemplate);
sendGet(function (response) {
document.getElementById('testData').innerHTML += template(response);
})
JSON:
JSON data format derives from JavaScript, so its more look like JavaScript objects, Douglas Crockford originally specified the JSON format, check here.
JavaScript Object Notation has set of rules.
Starts with open curly braces ( { ) and ends with enclosing curly braces ( } )
ex: {}
Inside baces you can add 'key' and its 'value' like { "title" : "hello json"}
here "title" is key and "hello json" is value of that key.
"key" should be string
"value" can be:
number
string
Boolean
array
object
Can not add JavaScript comments inside JSON (like // or /**/)
there are many online JSON validators, you can check whether your JSON is valid or not, check here.
When comes to linking JSON to js file, its more like provide an interface to get JSON data and use it in your JavaScript.
here XMLHttpRequest our interface. we usually call XMLHttpRequest API.
In the given js code, to get JSON from the server using an REST API (http://date.jsontest.com/)
for more information on REST API you can check here
from the url: http://date.jsontest.com/ you can get JSON object like below.
{
"time": "03:47:36 PM",
"milliseconds_since_epoch": 1471794456318,
"date": "08-21-2016"
}
Note: data is dynamic; values change on each request.
So by using external API you can get JSON, to use it in your JavaScript file/ code base you need to convert JSON to JavaScript object, JSON.parse( /* your JSON object is here */ ) converts JSON to js Object
`var responseObject = JSON.parse(xhr.responseText)`
by using dot(.) or bracket ([]) notation you can access JavaScript Object properties or keys; like below.
console.log(responseObject.time) //"03:47:36 PM"
console.log(responseObject["time"]) //"03:47:36 PM"
console.log(responseObject.milliseconds_since_epoch) //1471794456318
console.log(responseObject["milliseconds_since_epoch"])//1471794456318
console.log(responseObject.date) //"08-21-2016"
console.log(responseObject["date"]) //"08-21-2016"
So to link local JSON file (from your local directory) or an external API in your JavaScript file you can use "XMLHttpRequest".
'sendGet' function updatedin the above js block with comments please check.
In simple way:
create XMLHttpRequest instance
ex: var xhr = new XMLHttpRequest();
open request type
ex: xhr.open('GET', "http://date.jsontest.com/");
send "GET" request to server
ex: xhr.send();
register load event handler to hold JSON object if response has status code 200.
ex: xhr.onload = function () {
for more info check here
Know about these:
Object literal notation
difference between primitive and non-primitive data types
Existing references:
What is JSON and why would I use it?
What are the differences between JSON and JavaScript object?
Basically, JSON is a structured format recently uses which would be preferred due to some advantages via developers, Like simpler and easier structure and etc. Ajax is not a language, It's a technique that you can simply send a request to an API service and update your view partially without reloading the entire page.
So you need to make a server-client architecture. In this case all your server-side responses would be sent in JSON format as RESTful API. Also you can simply use the JSON response without any conversion or something else like an array object in JavaScript.
You can see some examples here to figure out better: JSON example
I have a web server returning an thrift object serialized used the JSON protocol to a client html page using the pure Javascript Thrift library (thrift.js).
The server for example:
from MyThriftFile.ttypes import ThriftClass
from thrift import TSerialization
from thrift.protocol import TJSONProtocol
thrift_obj = new ThriftClass()
result = TSerialization.serialize(
thrift_obj,
protocol_factory=TJSONProtocol.TJSONProtocolFactory())
return result
Now in the C#, Python, Java, and even the node.js Thrift libraries there is some form of this generic TSerialization or TDeserialization utlity and its more or less implemented like so:
def deserialize(base,
buf,
protocol_factory=TBinaryProtocol.TBinaryProtocolFactory()):
transport = TTransport.TMemoryBuffer(buf)
protocol = protocol_factory.getProtocol(transport)
base.read(protocol)
return base
So it gets it data, loads it up into a throw away transport (because we are not going to send this information anywhere), creates a new protocol object for encoding this data, and finally the actual thrift object reads this data to populate itself.
The pure javacript library however seems to lack this functionality. I understand why the client library only support the JSON protocol (web pages don't deal in raw binary data) but why not method for de/serialization from/to JSON?
I made my own method for doing the job but it seems hacky. Anyone have a better trick?
$(document).ready(function() {
$.get("www.mysite.com/thrift_object_i_want/", function(data, status) {
var transport = new Thrift.Transport();
var protocol = new Thrift.Protocol(transport);
// Sets the data we are going to read from.
transport.setRecvBuffer(data);
// This is basically equal to
// rawd = data
rawd = transport.readAll();
// The following is lifited from
// readMessageBegin().
// These params I am setting are private memeber
// vars that protocol needs set in order to read
// data set in setRevBuff()
obj = $.parseJSON(rawd);
protocol.rpos = []
protocol.rstack = []
protocol.rstack.push(obj)
// Now that the protocl has been hacked to function
// populate our object from it
tc = new ThriftClass();
tc.read(protocol);
// u is now a js object equal to the python object
});
});
I haven't tried your code but I assume it is working.
It seems correct and is essentially what the TSerializer et al classes do in those other languages. Granted, it could be wrapped in a more friendly way for the vanilla JS library.
The only thing that I might recommend to make it less "hacky" would be to just create a Thrift service method that returns the object(s) you need... then the serialization/deserialization logic will be automatically wrapped up nicely for you in the generated service client.
I am sending the following response from server :
return new OperationResult.Created { CreatedResourceUrl = getURI(newDuplicateKfEntity), ResponseResource = newDuplicateKfEntity };
My question is how can I get this CreatedResourceUrl object in my javascript??
Instead of OperationResult.Created return a typed DTO and use a Codec to encode it as Json. After that consuming Json in JavaScript is simple.