I have an ArrayBuffer object that I need to be able to convert to String to JSON, but I can't get the value of the [Int8Array] out of the object, even though it is clearly there.
I've tried all variations on this, but they all return undefined
console.log(result);//Returns the array buffer
//Following methods all return undefined?
console.log(result["[[Int8Array]]"]);
console.log(result[[[Int8Array]]]);
console.log(result[[["Int8Array"]]]);
console.log(result[Int8Array]);
console.log(result["Int8Array"]);
How can I get all the Int8Array or UInt8Array values that are clearly available in the object?
You can use the textDecoder that accepts ArrayBuffer (as well as uint8array) without having to deal with Uint8array's:
var str = new TextDecoder().decode(arrayBuffer)
var json = JSON.parse(str)
if you want to get straight to json
var json = await new Response(arrayBuffer).json()
You need to intiantiate a new Uint8Array to get their values, you can't access them directly using your ArrayBuffer instance.
var buf = new ArrayBuffer(8);
var int8view = new Uint8Array(buf);
console.log(int8view)
JSFiddle : https://jsfiddle.net/v8m7pjqb/
Related
I am trying to understand ArrayBuffer.
It seems like that if we use uint8Array directly, we get everything we need(typed array with fixed type).
We can do something like this:
var a = new Uint8Array(2)
a[0] = 10
a[1] = 20;
we can even do this = console.log(a.buffer) which means we still have a buffer meaning that Uint8Array itself is a buffer.
So why do we need ArrayBuffer class then ? What's the actual use case ?
I have a Uint8Array with an offset that I receive from another function. This contains the data I need, but there is a bit of other stuff at the start of the buffer backing this typed array.
The actual data are 32bit integers, and I'd like to have that data in an Int32Array. But converting this doesn't seem to be straightforward, I'm currently doing it manually the following way:
var outputBuffer = new ArrayBuffer(data.length);
var inputByteArray = new Uint8Array(outputBuffer);
for (var i=0; i < data.length; ++i) {
inputByteArray[i] = data[i]
}
var outputInt32Array= new Int32Array(outputBuffer);
The straightforward way of just creating a new Int32Array and passing the source Uint8Array doesn't work:
var outputInt32Array = new Int32Array(data) // data is the Uint8Array with offset
This results in a typed array that still behaves like a Uint8Array and hands out individual bytes, not 32bit integers.
Trying it by passing in the offset also doesn't work, I get the error "RangeError: start offset of Int32Array should be a multiple of 4":
var outputInt32Array = new Int32Array(data.buffer, data.byteOffset, length)
Is manually copying each byte the only way to get an Int32Array out of an Int8Array with an offset?
No, you don't need to manually copy the bytes from one to the other array. Using new Int32Array(data.buffer, …) is the best approach, but if you have a weird offset you will need to use a second buffer that is properly aligned. Still, you don't have to copy it manually, you can just use the slice method:
var outputInt32Array = new Int32Array(data.buffer.slice(data.byteOffset), 0, length);
If you need to access Int32s on the same buffer as data, you can also use a DataView.
How do I convert an array of bytes into ArrayBuffer in Nashorn? I am trying to insert binary data into a pure JavaScript environment (i.e., it doesn't have access to Java.from or Java.to) and so would like to create an instance out an array of bytes.
Looks like I was going about this the wrong way. It made more sense to convert it into Uint8Array since what I'm sending in is an array of bytes.
I created the following function:
function byteToUint8Array(byteArray) {
var uint8Array = new Uint8Array(byteArray.length);
for(var i = 0; i < uint8Array.length; i++) {
uint8Array[i] = byteArray[i];
}
return uint8Array;
}
This will convert an array of bytes (so byteArray is actually of type byte[]) into a Uint8Array.
I think you're right about using a Uint8Array, but this code might be preferable:
function byteToUint8Array(byteArray) {
var uint8Array = new Uint8Array(byteArray.length);
uint8Array.set(Java.from(byteArray));
return uint8Array;
}
Also, if you really need an ArrayBuffer you can use uint8Array.buffer.
I have this code:
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
localStorage.setItem('added-items', JSON.stringify(string));
This code will use localStorage.
Here is now the code to get the stored data:
var retrievedObject = localStorage.getItem('added-items');
My problem now is, how can i get the size of the data items? answer must be 2.
How can i get the "Item1" and "Item2"?
I tried retrievedObject[0][0] but it is not working.
And how to add data on it?
so it will be
{"items":[{"Desc":"Item1"},{"Desc":"Item2"},{"Desc":"Item3"}]}
Can I use JSON.stringify?
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
localStorage.setItem('added-items', JSON.stringify(string));
stringify means, take an object and return its presentation as a string.
What you have, is already a string and not a JSON object.
The opposite is JSON.parse which takes a string and turns it into an object.
Neither of them have anything to do with getting the size of an array. When properly coding JavaScript you almost never use JSON.parse or JSON.stringify. Only if serialization is explicitly wanted.
Use length for the size of the array:
var obj = {"items":[{"Desc":"Item1"},{"Desc":"Item2"},{"Desc":"Item3"}]}
console.debug(obj.items.length);
// THIS IS ALREADY STRINGIFIED
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
// DO NOT STRINGIFY AGAIN WHEN WRITING TO LOCAL STORAGE
localStorage.setItem('added-items', string);
// READ STRING FROM LOCAL STORAGE
var retrievedObject = localStorage.getItem('added-items');
// CONVERT STRING TO REGULAR JS OBJECT
var parsedObject = JSON.parse(retrievedObject);
// ACCESS DATA
console.log(parsedObject.items[0].Desc);
To bring clarity to future people that may stumble across this question and found the accepted answer to not be everything you hoped and dreamed for:
I've extended the question so that the user may either want to input a string or JSON into localStorage.
Included are two functions, AddToLocalStorage(data) and GetFromLocalStorage(key).
With AddToLocalStorage(data), if your input is not a string (such as JSON), then it will be converted into one.
GetFromLocalStorage(key) retrieves the data from localStorage of said key
The end of the script shows an example of how to examine and alter the data within JSON. Because it is a combination of objects and array, one must use a combination of . and [] where they are applicable.
var string = '{"items":[{"Desc":"Item1"},{"Desc":"Item2"}]}';
var json = {"items":[{"Desc":"Item1"},{"Desc":"Item2"},{"firstName":"John"},{"lastName":"Smith"}]};
localStorage.setItem('added-items', AddToLocalStorage(string));
localStorage.setItem('added-items', AddToLocalStorage(json));
// this function converts JSON into string to be entered into localStorage
function AddToLocalStorage(data) {
if (typeof data != "string") {data = JSON.stringify(data);}
return data;
}
// this function gets string from localStorage and converts it into JSON
function GetFromLocalStorage(key) {
return JSON.parse(localStorage.getItem(key));
}
var myData = GetFromLocalStorage("added-items");
console.log(myData.items[2].firstName) // "John"
myData.items[2].firstName = ["John","Elizabeth"];
myData.items[2].lastName = ["Smith","Howard"];
console.log(myData.items[2]) // {"firstName":["John","Elizabeth"],"lastName":["Smith","Howard"]}
console.log(myData.items.length) // 4
JSON.parse is definitely the best way to create an object but I just want to add if that doesn't work (because of lack of support), obj = eval('(' + str + ')'); should work. I've had a problem with a HTML to PDF converter in the past that didn't include JSON.parse and eval did the trick. Try JSON.parse first.
Access your object: obj.items[0].Desc;
var object = Json.parse(retrievedObject);
Now you can access it just like an array
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
If you need more help i have some previous code where i am reading Json from local storage and making a form from that json. This code will help in understanding how to traverse that array
Json stored in localstorage
{"form":[{"element":"input", "type":"text","name":"name","value":"value","min":"2","max":"10"}]}
JavaScript to read that json
function readJson(){
if(!form_created){
add_form();
}
var fetched_json = localStorage.getItem("json");
var obj=JSON.parse(fetched_json);
for(var i=0; i<obj.form.length;i++){
var input = document.createElement(obj.form[i].element);
input.name = obj.form[i].name;
input.value = obj.form[i].value;
input.type = obj.form[i].type;
input.dataset.min = obj.form[i].min;
input.dataset.max = obj.form[i].max;
input.dataset.optional = obj.form[i].optional;
form.insertBefore (input,form.lastChild);
}
alert(obj.form[0].name);
}
I have 4 bytes ArrayBuffer and I assigned a number at the index 0 using dataview. When I try to get the value using dataview that gives result correctly but it does not give correct result when I try to get value using typed array. Can anyone help on this? Here are the code:
var buffer = new ArrayBuffer(4);
var dataview = new DataView(buffer);
dataview.setUint32(0,5000);
var unint32 = new Uint32Array(buffer);
console.log(unint32[0]); //2282946560 instead of 5000
console.log(dataview.getUint32(0)); //shows correctly 5000
That's because you're using the wrong endian-type when using setUint32. Specifically, you need it to store a little-endian representation, because your hardware behaves like that.
You can see this more easily using hexadecimal values. Now, 5000 === 0x1388, while 2282946560 = 0x88130000. Can you see the pattern here?
Try this instead:
dataview.setUint32(0, 5000, true);
var unint32 = new Uint32Array(buffer);
console.log(unint32[0]); // 5000, yay!
As apsillers pointed out, if you're going to use dataview to retrieve the value too, you'll also have to use dataview.getUint32(0, true).
As a last word, if you just need to work with Uint32 numbers, forget about the DataView and use the typed array right away:
var buffer = new ArrayBuffer(4);
var unint32 = new Uint32Array(buffer);
unint32[0] = 5000;
You'll never get it wrong with this.
On the other hand, if you need to fill an ArrayBuffer with raw binary data, you'd like to check then endiannes of your hardware with this little trick.