This algorithm is pretty straightforward--something like the following should work:
function parse(a) {
//create object to return
var ret = {
columns: [],
data: []
};
//iterate the source array
a.forEach(function(item, i) {
if (i === 0) {
//first time through, build the columns
for (var key in item) {
ret.columns.push(key);
}
}
//now build your data item
ret.data[i] = [];
//use the column array to guarantee that the order of the fields in the source string doesn't matter
for (var j = 0; j < ret.columns.length; j++) {
var key = ret.columns[j];
ret.data[i].push(item[key]);
}
});
return ret;
}
var j = {
"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"NAME\":\"MERRY BLUE\",\"BIRTHDAY\":\"03-12-1983\",\"ID\":\"VN00000456\",\"GENDER\":\"Female\"},{\"GENDER\":\"Male\",\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"BIRTHDAY\":\"09-07-1990\"}]"
};
//j is an object with one property (d) that is a JSON string that needs parsing
var o = parse(JSON.parse(j.d));
console.log(o);
Answer from Dave on Stack Overflowjquery - How to parse JSON to JSON in javascript? - Stack Overflow
Javascript how to parse JSON array - Stack Overflow
javascript - How to parse JSON string in Typescript - Stack Overflow
why is JSON.parse way slower than parsing a javascript object in the source itself?
Videos
This algorithm is pretty straightforward--something like the following should work:
function parse(a) {
//create object to return
var ret = {
columns: [],
data: []
};
//iterate the source array
a.forEach(function(item, i) {
if (i === 0) {
//first time through, build the columns
for (var key in item) {
ret.columns.push(key);
}
}
//now build your data item
ret.data[i] = [];
//use the column array to guarantee that the order of the fields in the source string doesn't matter
for (var j = 0; j < ret.columns.length; j++) {
var key = ret.columns[j];
ret.data[i].push(item[key]);
}
});
return ret;
}
var j = {
"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"NAME\":\"MERRY BLUE\",\"BIRTHDAY\":\"03-12-1983\",\"ID\":\"VN00000456\",\"GENDER\":\"Female\"},{\"GENDER\":\"Male\",\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"BIRTHDAY\":\"09-07-1990\"}]"
};
//j is an object with one property (d) that is a JSON string that needs parsing
var o = parse(JSON.parse(j.d));
console.log(o);
You can try this example using jQuery:
https://jsfiddle.net/de02fpha/
var dump = {"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"ID\":\"VN00000456\",\"NAME\":\"MERRY BLUE\",\"GENDER\":\"Female\",\"BIRTHDAY\":\"03-12-1983\"},{\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"09-07-1990\"}]"};
var parse = function(json) {
var columns = [];
var data = [];
$.each(json, function(index, row) {
var element = [];
for (var key in row) {
if (columns.indexOf(key) == -1) columns.push(key);
element.push(row[key]);
}
data.push(element);
});
return {columns: columns, data: data};
};
var json = $.parseJSON(dump.d);
console.log(parse(json));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Javascript has a built in JSON parse for strings, which I think is what you have:
var myObject = JSON.parse("my json string");
to use this with your example would be:
var jsonData = JSON.parse(myMessage);
for (var i = 0; i < jsonData.counters.length; i++) {
var counter = jsonData.counters[i];
console.log(counter.counter_name);
}
Here is a working example
EDIT: There is a mistake in your use of for loop (I missed this on my first read, credit to @Evert for the spot). using a for-in loop will set the var to be the property name of the current loop, not the actual data. See my updated loop above for correct usage
IMPORTANT: the JSON.parse method wont work in old old browsers - so if you plan to make your website available through some sort of time bending internet connection, this could be a problem! If you really are interested though, here is a support chart (which ticks all my boxes).
In a for-in-loop the running variable holds the property name, not the property value.
for (var counter in jsonData.counters) {
console.log(jsonData.counters[counter].counter_name);
}
But as counters is an Array, you have to use a normal for-loop:
for (var i=0; i<jsonData.counters.length; i++) {
var counter = jsonData.counters[i];
console.log(counter.counter_name);
}
TypeScript is (a superset of) JavaScript, so you just use JSON.parse as you would in JavaScript:
let obj = JSON.parse(jsonString);
Only that in TypeScript you can also have a type for the resulting object:
interface MyObj {
myString: string;
myNumber: number;
}
let obj: MyObj = JSON.parse('{ "myString": "string", "myNumber": 4 }');
console.log(obj.myString);
console.log(obj.myNumber);
(code in playground)
Type-safe JSON.parse
You can continue to use JSON.parse, as TypeScript is a superset of JavaScript:
This means you can take any working JavaScript code and put it in a TypeScript file without worrying about exactly how it is written.
There is a problem left: JSON.parse returns any, which undermines type safety (don't use any).
Here are three solutions for stronger types, ordered by ascending complexity:
1. User-defined type guards
Playground
// For example, you expect to parse a given value with `MyType` shape
type MyType = { name: string; description: string; }
// Validate this value with a custom type guard (extend to your needs)
function isMyType(o: any): o is MyType {
return "name" in o && "description" in o
}
const json = '{ "name": "Foo", "description": "Bar" }';
const parsed = JSON.parse(json);
if (isMyType(parsed)) {
// do something with now correctly typed object
parsed.description
} else {
// error handling; invalid JSON format
}
isMyType is called a type guard. Its advantage is, that you get a fully typed object inside truthy if branch.
2. Generic JSON.parse wrapper
Playground
Create a generic wrapper around JSON.parse, which takes one type guard as input and returns the parsed, typed value or error result:
const safeJsonParse = <T>(guard: (o: any) => o is T) =>
(text: string): ParseResult<T> => {
const parsed = JSON.parse(text)
return guard(parsed) ? { parsed, hasError: false } : { hasError: true }
}
type ParseResult<T> =
| { parsed: T; hasError: false; error?: undefined }
| { parsed?: undefined; hasError: true; error?: unknown }
Usage example:
const json = '{ "name": "Foo", "description": "Bar" }';
const result = safeJsonParse(isMyType)(json) // result: ParseResult<MyType>
if (result.hasError) {
console.log("error :/") // further error handling here
} else {
console.log(result.parsed.description) // result.parsed now has type `MyType`
}
safeJsonParse might be extended to fail fast or try/catch JSON.parse errors.
3. External libraries
Writing type guard functions manually becomes cumbersome, if you need to validate many different values. There are libraries to assist with this task - examples (no comprehensive list):
io-ts: hasfp-tspeer dependency, uses functional programming stylezod: strives to be more procedural / object-oriented thanio-tstypescript-is: TS transformer for compiler API, additional wrapper like ttypescript neededtypescript-json-schema/ajv: Create JSON schema from types and validate it withajv
More infos
- Runtime type checking #1573
- Interface type check with Typescript
- TypeScript: validating external data
» npm install parse-json
I have 2MB of simple json (just an array of arrays) that I generate from a flask server and just dump into a javascript file to be executed by the browser. At first I did something like
var data = JSON.parse("{{json}}");but then I realized I could just do
var data = {{json}};for my simple data. I don't know if you can just dump json into javascript and get valid code, but I'm pretty sure that form my simple case it should work.
Here's my question: why does the first form take several seconds while the second is instantaneous (at least in chrome)? I would think that the parser for javascript would be more complex than the parser for JSON, and both would be implemented in native code, so where is this difference coming from?