Siesta: Child resources - json

I am having difficulties understanding how does Siesta figure out the child of a resource. For example I have the following events resource:
JSON returned by "/events"
{
"success": 1,
"events": [
{
"id": 1,
"type": "meeting",
"eventDate": "2015-08-20",
"notes": "fadsfasfa",
"title": null
},{
"id": 2,
"type": "game",
"eventDate": "2015-08-31",
"notes": "fdsafdf",
"title": null
}
]
}
Sadly, calling "/events/1" for example, does not return the event with id=2. Is there a way to tell Siesta which event has the id=2?

Suppose you have:
let events = myService.resource("/events")
Then you can navigate from the /events resource to the /events/2 resource like this:
let event = events.child("2")
That will give you the same object as if you had asked for myService.resource("/events/2").
To extract that 2 from the JSON, use normal Swift JSON parsing techniques. (Siesta doesn’t apply any special inspection or interpretation to the JSON once it’s parsed.) I recommend using the SwiftyJSON library for easier JSON traversal. For example, it lets you do something like this to extract those event IDs and get the child resources:
let allEventResources =
JSON(events.jsonDict)["events"]
.arrayValue
.flatMap { $0["id"].string }
.map(event.child)

Related

Parsing a very complex json response in dart

I'm trying to load a json file from a server response and parsing it in flutter, the model i create is working for all the other fields but i'm in trouble with this class
this is a part of the JSON response:
"episodes": {
"1": [
{
"id": "63",
"episode_num": 1,
"title": "Some Name",
"container_extension": "mp4",
"info": {
"director": "",
"plot": "",
"cast": "",
"rating": "",
"releasedate": "",
"movie_image": "",
"genre": "",
"duration_secs": 6495,
"duration": "01:48:15"
}
}
]
}
in this case the entry under episodes is just one but this will represents a season and all the episode inside it, so under episodes many of this entry (undefined number during coding) can be present
At this time, using online json to dart converter tools i can be able to retrive just this one entry but if a response have more than 1 season i can't see it.
There is any way to handle this?
EDIT:
Solved using a for cicle with max value = (json['episodes'].length + 1).
For the info stored inside each 'episodes' value i can use
json['episodes']['$i']
Valid JSON is always convertible to a Dart data structure. But what you may be asking is "can I get nested objects from this?", and that just depends on how hard you want to work. Some JSON-to-Dart tools are better than others and some JSON values are impossible for any automated tool to make sense of. Only real answer is: "it depends".

Executing a specific http method 'depending' on the condition given in the JSON file

I was thinking about the possibility of executing a specific http method (POST or PUT) in POSTMAN without specifying it.
I mean; imagine if there was a field in a JSON file called: METHOD within 2 possible states: 'I' corresponding to INSERT OR POST and the another one: 'U' related to UPDATE or PUT
Something like this: (please, do note the field called "method"):
[
{
"sku": "95LB645R34ER",
"method": 'I'
"payload": {
"price": "147000",
"tax_percentage": "US-21",
"store_code": "B2BUSD",
"markup_top": "1.62",
"status": "1",
"group_prices": [
{
"group": "CLASS A",
"price": "700038.79",
"website": "B2BUSD"
}
]
}
},
{
"sku": "95TYS34344ER",
"method": 'U'
"payload": {
"price": "69978",
"tax_percentage": "US-21",
"store_code": "B2BUSD",
"markup_top": "9.99",
"status": "1",
"group_prices": [
{
"group": "CLASS B",
"price": "88888.79",
"website": "B2BUSD"
}
]
}
}
]
I would like to run that JSON using the Collection Runner but i have no idea how to do the trick. I mean, everytime i generate a collection i have to specify the HTTP METHOD otherwise it wont know what to do.
I want the program to adjust that by looking at the JSON file, if "method":'I' then, perform a POST or if "method":'U' execute a PUT method. Do you get me?
I've been reading the documentation but i did not find something like that or maybe i did not understand. I'm not an expert on POSTMAN :(
Can you help me?
EDIT:
Alright, i did this:
In the request UI, use the {{METHOD}} syntax where you would see the HTTP method. This is an editable field as it allows you to add custom HTTP methods.
In the file, use the METHOD key and any HTTP verb as the value. Ensure that it's part of each object in the datafile as you will need it for each iteration.

Is returning only IDs for a JSON API collection allowed?

So let's say I have a resources called articles. These have a numeric id and you can access them under something such as:
GET /articles/1 for a specific article.
And let's say that returns something like:
{
"data": {
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON:API paints my bikeshed!",
"body": "A bunch of text here"
}
}
}
Now my question is how to handle a request to GET /articles. I.e. how to deal with the request to the collection.
You see, accessing the body of the article is slow and painful. The last thing I want this REST API to do is actually try to get all that information. Yet as far as I can tell the JSON API schema seems to assume that you can always return full resources.
Is there any "allowed" way to return just the IDs (or partial attributes, like "title") under JSON API while actively not providing the ability to get the full resource?
Something like:
GET /articles returning:
{
"data": [
{
"type": "article_snubs",
"id": 1,
"attributes": {
"title": "JSON:API paints my bikeshed!"
}
}, {
"type": "article_snubs",
"id": 2,
"attributes": {
"title": "Some second thing here"
}
}
]
}
Maybe with links to the full articles?
Basically, is this at all possible while following JSON API or a REST standard? Because there is absolutely no way that GET /articles is ever going to be returning full resources due to the associate cost of getting the data, which I do not think is a rare situation to be in.
As far as I understand the JSON API specification there is no requirement that an API must return all fields (attributes and relationships) of a resource by default. The only MUST statement regarding fields inclusion that I'm aware of is related to Sparse Fieldsets (fields query param):
Sparse Fieldsets
[...]
If a client requests a restricted set of fields for a given resource type, an endpoint MUST NOT include additional fields in resource objects of that type in its response.
https://jsonapi.org/format/#fetching-sparse-fieldsets
Even so this is not forbidden by spec I would not recommend that approach. Returning only a subset of fields makes consuming your API much harder as you have to consult the documentation in order to get a list of all supported fields. It's much more within the meaning of the spec to let the client decide which information (and related resources) should be included.
The "attributes" object of a JSON-API doc does not need to be a complete representation:
attributes: an attributes object representing some of the resource’s data.
You can provide a "self" link to get the full representation, or perhaps even a "body" link to get just the body:
links: a links object containing links related to the resource.
E.g.
{
"data": [
{
"type": "articles_snubs",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"links": {
"self": "/articles/1",
"body": "/articles/1/body"
}
},
{
"type": "article_snubs",
"id": "2",
"attributes": {
"title": "Some second thing here"
},
"links": {
"self": "/articles/2",
"body": "/articles/2/body"
}
}
]
}

Streaming huge json with Akka Stream

I have a problem of huge http response with a json slab, where only portion is point of interest.
I cannot change the response structure.
here is an example
{
"searchString": "search",
"redirectUrl": "",
"0": {
"numRecords": 123,
"refinementViewModelCollector": {},
// Lots of data here
"results": [
{
"productCode": "123",
"productShortDescription": "Desc",
"brand": "Brand",
"productReview": {
"reviewScore": 0
},
"priceView": {
"salePriceDisplayable": false,
},
"productImageUrl": "url",
"alternateImageUrls": [
"url1"
],
"largeProductImageUrl": "url4",
"videoUrl": ""
},
{
"productCode": "124",
"productShortDescription": "Desc",
"brand": "Brand",
"productReview": {
"reviewScore": 0
},
"priceView": {
"salePriceDisplayable": false,
},
"preOrder": false,
"productImageUrl": "url",
"alternateImageUrls": [
"url1"
],
"largeProductImageUrl": "url4",
"videoUrl": ""
}
]
//lots of data here
}
}
My point of interest is entries in results Jason Array, but the are sitting in the middle of json
I created a small Play WS Client like this:
val wsClient: WSClient = ???
val ret = wsClient.url("url").stream()
ret.flatMap { response =>
response.body.via(JsonFraming.objectScanner(1024))
.map(_.utf8String)
.runWith(Sink.foreach(println))
}
this will not work because it will take whole json slab as Json object. I need to skip some data until "results": entry appear in the stream, then start parsing entries and skip all the rest.
Any ideas how to do this?
Check out Alpakka's JSON module, which can stream specific parts of a nested JSON structure:
response
.body
.via(JsonReader.select("$.0.results[*]"))
.map(_.utf8String)
.runWith(Sink.foreach(println)) // or runForeach(println)
There are parsers that support parsing as a stream. For a good example check out this Circe example https://github.com/circe/circe/tree/master/examples/sf-city-lots
I'd love a better, Scala-specific answer to this question, but check out the "Mixed Reads Example" in the documentation for Google's GSON library:
https://sites.google.com/site/gson/streaming
Gson also supports mixed streaming & object model access. This lets your application have the best of both worlds: the productivity of object model access with the efficiency of streaming
...
This code reads a JSON document containing an array of messages. It steps through array elements as a stream to avoid loading the complete document into memory. It is concise because it uses Gson’s object-model to parse the individual messages
This should have great memory-performance (the code reads from a Java InputStream, so the full structure is never in memory), but may require some effort to get your results into Scala case classes.

How to do deep sets and gets in Go's map[string]interface{}?

If I have some arbitrary JSON how can I do deep sets and gets on the nested properties using a slice of map keys and/or slice indexes?
For example, in the following excerpt from the JSON API example:
{
"data": [{
"type": "posts",
"id": "1",
"title": "JSON API paints my bikeshed!",
"links": {
"self": "http://example.com/posts/1",
"author": {
"self": "http://example.com/posts/1/links/author",
"related": "http://example.com/posts/1/author",
"linkage": { "type": "people", "id": "9" }
}
}
}]
}
I'd like to get the string "9" located at data.0.links.author.linkage.id using something like:
[]interface{}{"data",0,"links","author","linkage","id"}
I know the ideal way to do this is to create nested structs that map to the JSON object which I do for production code, but sometimes I need to do some quick testing which would be nice to do in Go as well.
You have stretchr/objx that provide a similar approach.
Example use:
document, _ := objx.FromJSON(json)
document.Get("path.to.field[0].you.want").Str()
However, unless you really don't know at all the structure of your JSON input ahead of time, this isn't the preferred way to go in golang…