Read JSON Data With String Key: Angular2 - json

I am trying to iterate json data in angular2.
If JSON Data is like this
{fileName: "XYZ"}
I am able to iterate using- let data of datas
But If my JSON data key is in string format, how I can iterate in angular2?
{"fileName": "XYZ"}

JSON always have double quoted string keys, so these:
{ fileName: "XYZ" }
{ 'fileName': "XYZ" }
Are not valid jsons, but this is:
{ "fileName": "XYZ" }
Javascript objects don't require the keys to be quoted, and if they are then a single quote can be used:
let a = { fileName: "XYZ" };
let b = { 'fileName': "XYZ" };
let c = { "fileName": "XYZ" };
Here a, b and c are equivalent.
In any case, iterating all of those js object is done in the same way:
for (let key in a) {
console.log(`${ key }: ${ a[key] }`);
}
Object.keys(b).forEach(key => console.log(`${ key }: ${ b[key] }`));

Related

What is "\" in JSON?

I am practicing JSON parsing and I encountered this kind of JSON
{
"data": {
"Location": "[{\"id\":\"asdiqwe321\",\"name\":\"Manila\",\"lat\":25.42952,\"long\":-96.7960712,\"rating\":3,\"address\":\"Manila Ph\"},{\"place_id\":\"zzxdasdqwe1235as\",\"name\":\"Quezon City Ph.\",\"lat\":12.523562,\"long\":24.663415,\"rating\":1,\"address\":\"Quezon City Ph\"},{\"place_id\":\"rtiDFSDQ1321\",\"name\":\"Makati\",\"lat\":32.151236,\"long\":21.24124561,\"rating\":3.5,\"address\":\"Makati PH\"}]"
}
}
I have a model and want to cast it there:
export interface Location{
place_id: string,
name: string,
lat: number,
long: number,
rating: number,
address: number
}
This is my first time to encountered this type of JSON. I hope someone will help me and understand what is it.
That's not a JSON Object, that's a string. The \ character is used to escape the double quote ", otherwise JavaScript would interpret the double quote as the end of the string and would throw a parsing error.
If you want to access the string as an object, you need to parse it using JSON.parse:
const obj = {
"data": {
"Location": "[{\"id\":\"asdiqwe321\",\"name\":\"Manila\",\"lat\":25.42952,\"long\":-96.7960712,\"rating\":3,\"address\":\"Manila Ph\"},{\"place_id\":\"zzxdasdqwe1235as\",\"name\":\"Quezon City Ph.\",\"lat\":12.523562,\"long\":24.663415,\"rating\":1,\"address\":\"Quezon City Ph\"},{\"place_id\":\"rtiDFSDQ1321\",\"name\":\"Makati\",\"lat\":32.151236,\"long\":21.24124561,\"rating\":3.5,\"address\":\"Makati PH\"}]"
}
};
const locationString = obj.data.Location;
const locationObject = JSON.parse(locationString);
console.log(locationObject[0].id);
If you don't parse it, instead, obj.data.Location is just a string:
const obj = {
"data": {
"Location": "[{\"id\":\"asdiqwe321\",\"name\":\"Manila\",\"lat\":25.42952,\"long\":-96.7960712,\"rating\":3,\"address\":\"Manila Ph\"},{\"place_id\":\"zzxdasdqwe1235as\",\"name\":\"Quezon City Ph.\",\"lat\":12.523562,\"long\":24.663415,\"rating\":1,\"address\":\"Quezon City Ph\"},{\"place_id\":\"rtiDFSDQ1321\",\"name\":\"Makati\",\"lat\":32.151236,\"long\":21.24124561,\"rating\":3.5,\"address\":\"Makati PH\"}]"
}
};
console.log(typeof obj.data.Location);
You usually need to stringify or parse objects for serializations purpose.
It is Array of object of type Location in serialized form.
var response = {
"data": {
"Location": "[{\"id\":\"asdiqwe321\",\"name\":\"Manila\",\"lat\":25.42952,\"long\":-96.7960712,\"rating\":3,\"address\":\"Manila Ph\"},{\"place_id\":\"zzxdasdqwe1235as\",\"name\":\"Quezon City Ph.\",\"lat\":12.523562,\"long\":24.663415,\"rating\":1,\"address\":\"Quezon City Ph\"},{\"place_id\":\"rtiDFSDQ1321\",\"name\":\"Makati\",\"lat\":32.151236,\"long\":21.24124561,\"rating\":3.5,\"address\":\"Makati PH\"}]"
}
}
You have to parse it.
var locationData : Array<Location> = JSON.Parse(response.data.Location);

Parsing JSON using codable and ignoring first layer of JSON

I have JSON like this:
{
"success": true,
"message": "",
"result": {
"buy": [
{
"Quantity": 0.0056,
"Rate": 18527
},
{
"Quantity": 0.11431426,
"Rate": 18526
}
],
"sell":[
{
"Quantity": 8.20604116,
"Rate": 18540
},
{
"Quantity": 0.95600491,
"Rate": 18574.99999998
}
]
}
}
and another set of JSON like this:
{
"lastUpdateId": 1027024,
"bids": [
[
"4.00000000", // PRICE
"431.00000000", // QTY
[] // Can be ignored
]
],
"asks": [
[
"4.00000200",
"12.00000000",
[]
]
]
}
What is the best way to parse these two responses using codable. They both need to be parsed using the same struct or need to be converted to the same struct (whatever will do the job faster). I don't want to create a struct for the entire first response because I am not going to use keys like "success" and "message". I basically want to ignore those and get directly to the "result" key But in the second response, I will being using all the data so I have created a struct for that called TotalOrderBook. What is the best way to do this?
What is confusing me is ignoring the keys "success" and "message" in the first JSON response and getting straight to the value for the key "result". Is it possible to do that without creating an additional struct?
This is what I have right now. I would like to avoid adding another struct since the only thing I really need is the values under buy/bid and sell/sell.
struct TotalOrderBook:Codable{
var buy:[UniversalOrder]?
var sell:[UniversalOrder]?
var bid:[UniversalOrder]?
var ask:[UniversalOrder]?
var buyOrderBook: [UniversalOrder] {
return bid ?? buy ?? [UniversalOrder]()
}
var sellOrderBook: [UniversalOrder] {
return ask ?? sell ?? [UniversalOrder]()
}
var updatedTime:Date
}
struct UniversalOrder:Codable{
var price : Double {
return Double(rate ?? binPrice ?? 0)
}
var size : Double {
return Double(quantity ?? binQuantity ?? 0 )
}
//let numOrders : Int
var quantity:Double?
var rate:Double?
var binPrice:Double?
var binQuantity:Double?
private enum CodingKeys: String, CodingKey {
case rate = "Rate"
case quantity = "Quantity"
//case numOrders, binPrice,
}
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
binPrice = Double(try container.decode(String.self)) ?? nil
binQuantity = Double(try container.decode(String.self)) ?? nil
quantity = nil
rate = nil
}
}
This is how I am decoding:
let decoder = JSONDecoder()
let data = try! JSONSerialization.data(withJSONObject: value) //value is the response from Alamofire
var theWholeOrderBook:UniversalOrder!
do {
theWholeOrderBook = try decoder.decode(UniversalOrder.self, from: data)
} catch let error {
//print ("error is \(e) ** \(value)")
}
To answer your questions directly, yes it is very easy to ignore the success and message key-value pairs and head straight to results.
Despite this it will be a bit complicated to have a single struct to parse both of these JSON responses.
Both of them have a very different structure which will make it easier to use two different structs to use encoding. To highlight some differences :
buy, sell are nested inside results. bids, asks aren't.
The keys are completely different.
buy, sell have an array of key-value pairs while bids, asks simple have an array of values.
Codable structs should be simple and clear. It's better to have two of those corresponding to each response.

How to parse partial objects inside Json

I have the Json structure below, and i'm trying to parse only the key field inside the object. It's possible to do it without mapping the complete structure?
{
"Records":[
{
"eventVersion":"2.0",
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"my-event",
"bucket":{
"name":"super-files",
"ownerIdentity":{
"principalId":"41123123"
},
"arn":"arn:aws:s3:::myqueue"
},
"object":{
"key":"/events/mykey",
"size":502,
"eTag":"091820398091823",
"sequencer":"1123123"
}
}
}
]
}
// Want to return only the Key value
type Object struct {
Key string `json:"key"`
}
There are a few 3rd party json libraries which are very fast at extracting only some values from your json string.
Libraries:
http://jsoniter.com/
https://github.com/tidwall/gjson
https://github.com/buger/jsonparser
GJSON example:
const json = `your json string`
func main() {
keys := gjson.Get(json, "Records.#.s3.object.key")
// would return a slice of all records' keys
singleKey := gjson.Get(json, "Records.1.s3.object.key")
// would only return the key from the first record
}
Object is part of S3, so I created struct as below and I was able to read key
type Root struct {
Records []Record `json:"Records"`
}
type Record struct {
S3 SS3 `json:"s3"`
}
type SS3 struct {
Obj Object `json:"object"`
}
type Object struct {
Key string `json:"key"`
}

Building JSON dynamically in Swift

I'm trying to build some JSON in Swift. I've seen some examples of turning a Dictionary into JSON or a class into JSON, but I want to be able to turn data into JSON on the fly. I also have multiple objects I want to store, not just one (which most examples I find seem to do).
Here is my code that creates dictionaries of the objects I want to store:
for topic in topics{
var relEntries = getRelevantEntries(topic.id)
var entryItem:[String:Any] = ["":""]
for entry in relEntries{
var eId = ["id":entry.id]
var eTitle = ["title":entry.title]
entryItem = [
"id":entry.id,
"title":entry.title
]
}
var topicItem:[String:Any] = [
"id":topic.id,
"topicName":topic.name,
"entries":entryItem
]
}
I want to create a JSON Array, where each object includes an int, string, and another JSON Array. I wrote out a demo table to clarify.
[
{ id: "id",
topicName: "topicName",
entries:[
{ id: "id", title: "title" },
{ id: "id2", title: "title2"}
]},
{ id: "id2",
topicName: "topicName2",
entries:[
{ id: "id", title: "title" },
{ id: "id2", title: "title2"}
]}
]
So where do I go from here to combine all my topics into one JSON Array? Thanks.
You can use serialization techniques on your custom objects to build Foundation types that represent them.
After that, you can use the NSJSONSerialization class to generate the json.
Since you have to differentiate between your different classes, there is less except handling with mirrors that might generalize that work for you at this point in time, afaik.
You say:
I want to create a JSON Array, where each object includes an int, string, and another JSON Array. I wrote out a demo table to clarify.
[
{ id: "id",
topicName: "topicName",
entries:[
{ id: "id", title: "title" },
{ id: "id2", title: "title2"}
]},
{ id: "id2",
topicName: "topicName2",
entries:[
{ id: "id", title: "title" },
{ id: "id2", title: "title2"}
]}
]
Well, what is that? It's an array ([...]) of dictionaries ({...}), where each dictionary has an id key (with a string value), a topicName key (with a string value), and an entries key, where each entries value is an array containing two dictionaries with an id key and a title key (each with a string value).
So your job is merely to construct that structure and serialize it into JSON. That's trivial. Here, as a mockup, I'll demonstrate using literals:
var d1 : [NSObject:AnyObject] = ["id":"id", "topicName":"topicName"]
var d2 : [NSObject:AnyObject] = ["id":"id2", "topicName":"topicName2"]
let dd1 = ["id":"id", "title":"title"]
let dd2 = ["id":"id2", "title":"title2"]
let arr1 = [dd1,dd2]
let arr2 = [dd1,dd2]
d1["entries"] = arr1
d2["entries"] = arr2
let arr = [d1,d2]
let d = try! NSJSONSerialization.dataWithJSONObject(arr, options: [])
let s = NSString(data: d, encoding: NSUTF8StringEncoding)
print(s!)
Output:
[
{"id":"id",
"entries":[
{"id":"id","title":"title"},
{"id":"id2","title":"title2"}
],
"topicName":"topicName"
},
{"id":"id2",
"entries":[
{"id":"id","title":"title"},
{"id":"id2","title":"title2"}
],
"topicName":"topicName2"
}
]
I believe you'll find that that's exactly the equivalent of what you asked for. Now all you have to do is write code that converts your original data structure into the data structure that I constructed above out of literals.

JsonNode in JSON in Rust

I ran through the standard JSON library of Rust http://doc.rust-lang.org/serialize/json/ and couldn't figure out what represents a node in it. In Java it's JsonNode. What's it in Rust? For example, how can I pass an argument of the type JsonNode in Rust?
Rust's "DOM" for JSON is defined by Json enum. For example, this JSON object:
{ "array": [1, 2, 3], "submap": { "bool": true, "string": "abcde" } }
is represented by this expression in Rust:
macro_rules! tree_map {
($($k:expr -> $v:expr),*) => ({
let mut r = ::std::collections::TreeMap::new();
$(r.insert($k, $v);)*
r
})
}
let data = json::Object(tree_map! {
"array".to_string() -> json::List(vec![json::U64(1), json::U64(2), json::U64(3)]),
"submap".to_string() -> json::Object(tree_map! {
"bool".to_string() -> json::Boolean(true),
"string".to_string() -> json::String("abcde".to_string())
})
});
(try it here)
I've used custom map construction macro because unfortunately Rust standard library does not provide one (yet, I hope).
Json is just a regular enum, so you have to use pattern matching to extract values from it. Object contains an instance of TreeMap, so then you have to use its methods to inspect object structure:
if let json::Object(ref m) = data {
if let Some(value) = m.find_with(|k| "submap".cmp(k)) {
println!("Found value at 'submap' key: {}", value);
} else {
println!("'submap' key does not exist");
}
} else {
println!("data is not an object")
}
Update
Apparently, Json provides a lot of convenience methods, including find(), which will return Option<&Json> if the target is an Object which has corresponding key:
if let Some(value) = data.find("submap") {
println!("Found value at 'submap' key: {}", value);
} else {
println!("'submap' key does not exist or data is not an Object");
}
Thanks #ChrisMorgan for the finding.