Dealing with tree-like data structures in JSON API - json

Let's say we have several resources, that can exist by themselves or can be organized in a tree-like hierarchy. I called them roots, branches and leafs just for convenience. Now I want to retrieve leaf's data:
GET /leaf/1
Accept: application/vnd.api+json
which must return me something like this according to JSON API spec:
{
"data": [{
"type": "leaf",
"id": "1",
"title": "Leaf 1",
"links": {
"self": "http://example.com/leaf/1",
"branch": {
"self": "http://example.com/leaf/1/links/branch",
"related": "http://example.com/leaf/1/branch",
"linkage": { "type": "branch", "id": "5" }
},
"root": {
"self": "http://example.com/leaf/1/links/root",
"related": "http://example.com/leaf/1/root",
"linkage": { "type": "root", "id": "7" }
}
}
}],
"included": [{
"type": "branch",
"id": "5",
"title": "Branch 5",
"links": {
"self": "http://example.com/branch/5"
}
}, {
"type": "root",
"id": "7",
"title": "Root 7",
"links": {
"self": "http://example.com/root/7"
}
}]
}
From the response data I can't say that the data is hierarchical and it seems appropriate to change leaf's root:
PATCH /leaf/1
Content-Type: application/vnd.api+json
{
"data": {
"type": "leaf",
"id": 1,
"links": {
"root": {
"linkage": { "type": "root", "id": "3"}
}
}
}
}
Which is of course not possible because this leaf is connected to the branch and only then to the root, and changing the root in the schema below requires to have an id of this root's branch. Questions are:
How (if it's possible) to represent a hierarchy in the resource
representation to make it clear to an API user that the changing
relationships may require additional data?

The problem with your example is that you are viewing your data as leafs and branches, not separate objects.
REST is about managing entities. Try to look at REST URL as a name of the entity. Not some fancy tree pointer.
So, in your case PATCHing leafs is not possible like that. To change an entity you must use the same path you used to create it.

I know this answer is late, but I'm just leaving it here for others in the future.
I think the way to go is to replace the "branch" and "root" relationships with a single "parent" relationship that points to the parent node (which is of course on a branch under some root). Then, the parent relationship can be patched to any other node, without an inconsistency being introduced (since that was the problem before with someone patching root but not branch).
Then, if you still want to expose the root node, not just the direct parent, you could put this information in meta somewhere, you could add back a "root" relationship but not make it writeable (I.e. PATCH attempts would return 400/403), etc.

Related

Fiware Upload Image

I want to know how to use NSGI-LD to upload an image even though these static files are not stored in Orion Context Broker or Mongo. I want to know if there is a way to configure the NSGI-LD to forward the images to AWS S3 Buck or another location?
As you correctly identified, binary files are not a good candidate for context data, and should not be held directly within a context broker. The usual paradigm would be as follows:
Imagine you have a number plate reader library linked to Kurento and wish to store the images of vehicles as they pass. In this case the event from the media stream should cause two separate actions:
Upload the raw image to a storage server
Upsert the context data to the context broker including an attribute holding the URI of the stored image.
Doing things this way means you can confirm that the image is safely stored, and then send the following:
{
"vehicle_registration_number": {
"type": "Property",
"value": "X123RPD"
},
"image_download": {
"type": "Property",
"value": "http://example.com/url/to/image"
}
}
The alternative would be to simply include some link back to the source file somehow as metadata:
{
"vehicle_registration_number": {
"type": "Property",
"value": "X123RPD",
"origin": {
"type": "Property",
"value": "file://localimage"
}
}
}
Then if you have a registration on vehicle_registration_number which somehow links back to the server with the original file, it could upload the image after the context broker has been updated (and then do another upsert)
Option one is simpler. Option two would make more sense if the registration is narrower. For example, only upload images of VRNs for cars whose speed attribute is greater than 70 km/h.
Ontologically you could say that Device has a relationship to a Photograph which would mean that Device could have an additional latestRecord attribute:
{
"latestRecord": {
"type": "Relationship",
"object": "urn:ngsi-ld:CatalogueRecordDCAT-AP:0001"
},
}
And and create a separate entity holding the details of the Photograph itself using a standard data model such as CatalogueRecordDCAT-AP which is defined here. Attributes such as source and sourceMetadata help define the location of the raw file.
{
"id": "urn:ngsi-ld:CatalogueRecordDCAT-AP:0001",
"type": "CatalogueRecordDCAT-AP",
"dateCreated": "2020-11-02T21:25:54Z",
"dateModified": "2021-07-02T18:37:55Z",
"description": "Speeding Ticket",
"dataProvider": "European open data portal",
"location": {
"type": "Point",
"coordinates": [
36.633152,
-85.183315
]
},
"address": {
"streetAddress": "2, rue Mercier",
"addressLocality": "Luxembourg",
"addressRegion": "Luxembourg",
"addressCountry": "Luxembourg",
"postalCode": "2985",
"postOfficeBoxNumber": ""
},
"areaServed": "European Union and beyond",
"primaryTopic": "Public administration",
"modificationDate": "2021-07-02T18:37:55Z",
"applicationProfile": "DCAT Application profile for data portals in Europe",
"changeType": "First version",
"source": "http://example.com/url/to/image"
"sourceMetadata": {"type" :"jpeg", "height" : 100, "width": 100},
"#context": [
"https://smartdatamodels.org/context.jsonld"
]
}

FHIR one actor in two different roles

I'm creating a procedure in a transaction bundle and add practitioners as actors to the performers collection, having different functions. As far as the practitioners references are unique, all is fine. But when I'm trying to add a practitioners twice, with a different functions, an exception is thrown:
Can not process entity with ID[urn:uuid:7165d406-da59-4436-aa93-372ca882c4e5], this is not a valid FHIR ID
I found this message in HAPI FHIR unit tests, but in my case, the uuid seems to be fine. But maybe only one uuid is replaced with the id of the created practitioner.
I'm also not sure, whether this is the correct way for what I want to achieve.
I also tried to add the practioner only once and then add the second role to function.coding. But the resulting entry looks for me kinda strange:
performer": [
{
"function": {
"coding": [
{
"system": "http://somewhere/performer-role",
"code": "88888888"
},
{
"system": "http://somewhere/performer-role",
"code": "99999999",
"display": "Role-2"
}
],
"text": "Role-1"
},
"actor": {
"reference": "Practitioner/2925"
}
},
I'm fairly new to Fhir. Does anybody knows what's wrong here ?
And, what's the recommended practice, to have one performer/actor in to different roles ?
Thanks in advance
P.S. I'm using HAPI FHIR 4.0
Multiple coding repetitions would be used to convey translations - so you're saying that 888888888 and 99999999 are two different codes that represent the same role. If you want to indicate that the same Practitioner had two different roles, then you need to have two different performer repetitions. E.g.
perfomer: [
{
"function": {
"coding": [ {
"system": "http://somewhere/performer-role",
"code": "88888888"
}]},
"actor": {
"reference": "Practitioner/2925"
}
}, {
"function": {
"coding": [ {
"system": "http://somewhere/performer-role",
"code": "99999999"
}]},
"actor": {
"reference": "Practitioner/2925"
}
}
]

Elastic Search + JSON import (ELK Stack)

I'm currently trying to do a basic JSON file import into my ELK stack. I tried importing it directly via a POST request like this:
curl -XPOST http://localhost:9200/kwd_results/TS_Cart -d #/home/local/TS_Cart.json
ES says ok for the import, but when I'm trying to view the logs in Kibanna, they are not indexed by the nodes of the JSON file. I'm guessing I need like a template mapping to view it properly.
My JSON file looks like this:
{
"testResults": {
"FitNesseVersion": "v20160618",
"rootPath": "K1System.CountryDe.DriverFirefox.TestCases.MainFolder.TestVariants.SmokeTests_B2C.TS_Cart",
"result": [
{
"counts": {
"right": "16",
"wrong": "2",
"ignores": "3",
"exceptions": "1"
},
"date": "2017-05-10T00:01:11+02:00",
"runTimeInMillis": "117242",
"relativePageName": "TestCase_1",
"pageHistoryLink": "K1System.CountryDe.DriverFirefox.TestCases.MainFolder.TestVariants.SmokeTests_B2C.TS_Cart.B2CFreeCatalogueOrder?pageHistory&resultDate=20170510000111",
"tags": "de, at"
},
{
"counts": {
"right": "16",
"wrong": "0",
"ignores": "0",
"exceptions": "0"
},
"date": "2017-05-10T00:03:08+02:00",
"runTimeInMillis": "85680",
"relativePageName": "TestCase_2",
"pageHistoryLink": "K1System.CountryDe.DriverFirefox.TestCases.MainFolder.TestVariants.SmokeTests_B2C.TS_Cart.B2CGiftCardOrderWithAdvancePayment?pageHistory&resultDate=20170510000308",
"tags": "at, de"
}
],
"finalCounts": {
"right": "4",
"wrong": "1",
"ignores": "0",
"exceptions": "0"
},
"totalRunTimeInMillis": "482346"
}
}
Basically I would need rootPath to be used as an index, while having the following childs: counts, relativePageName, date and tags. Notice that I have two nodes that are childs of the result[] array.
Any help would be greatly appreciated!
Thank you.
Well, it's one JSON document so Elasticsearch treats it as such.
You'll need to (programmatically) split up the document into the right documents and then you can store them (potentially with one _bulk request).
For the index name:
Must be lowercase, so you'll need to cast that value.
Will you have many different root paths with jut a few docs each? Then you shouldn't make all of them an index since there is an overhead for each one of them (actually the underlying shards).

Reading complex json data without iteration

I am working with some data and often the data is nested and i am required to perform some CRUD operations based on the structure of the data i have. For instance i have this json structure
{
"_id": "KnNLkJEhrDsvWedLu",
"createdAt": {
"$date": "2016-10-13T11:24:13.843Z"
},
"services": {
"password": {
"bcrypt": "$2a$30$1/cniPwPNCuwZ/MQDPQkLej..cAATkoGX.qD1TS4iHgf/pwZYE.j."
},
"email": {
"verificationTokens": [
{
"token": "qxe_T9IS7jW7gntpK0Q7UQ35RJ9jO9m2lclnokO3z87",
"address": "drwho#gmail.com",
"when": {
"$date": "2016-10-13T11:24:14.428Z"
}
}
]
},
"resume": {
"loginTokens": []
}
},
"username": "doctorwho",
"emails": [
{
"address": "drwho#gmail.com",
"verified": false
}
],
"persodata": {
"lastlogin": {
"$date": "2016-10-13T11:29:36.816Z"
},
"fname": "Doctor",
"lname": "Who",
"mobile": "+4480000000",
"identity": "1",
"email": "drwho#gmail.com",
"gender": null
}
}
I have several data sets with such complex structure. I need to read the data, edit and also delete. Before i get to iteration, i was wondering how i can read the data without iteration then iterate when i absolutely have to.
What are the rules i should keep in mind when reading such complex json structures to enable me read any complex structure i come across?.
I am currently using javascript but i am looking for rules that apply in other languages as well.
Parsing Json in JavaScript should be easy. http://www.json.org/js.html.
"Since JSON is a proper subset of JavaScript, the compiler will correctly parse the text and produce an object structure". Just follow the examples on that page.
If you want to use another language, in Java you could use Jackson or Gson to map those json strings to objects. Then using them becomes easy. Both libraries are annotation based, and wouldn't be difficult to implement.

How to merge JPA entity structure on a POST/PUT RESTful webapp

I am starting to implement a REST layer to an existing JSF-webapp (using RESTEasy, with a Jettison provider). Since tutorials for Java REST layers are quite basic (simple objects) I am facing the question how existing JPA entity relations can be easily exposed to/consumed from the client. A simple "/user" REST-method already gives me successfully the output below, which is a good start. But my main question is - how to deal with this kind of structures. Is it common to use such structures through REST?
I don't want to expose all details or the whole entity-tree, wether it is because of irrelevance, saving traffic or security issues. Using #XmlTransient works fine for the #Procudes, but merging these entities on a #POST/#PUT all #XmlTransient properties are merged to NULL. What is right way of doing that?
Since #XMLTransient is a global and permanent setting - what is the right approach to dynamically decide which depth of entity-tree I want to expose?
thanks
Example JSON of User-entity:
{
"user": {
"id": ..,
"uuid": "1521ccad69ba4579bbe49e75181fefc1",
"image": "",
"contact": {
"id": ..,
"uuid": "8eb429dcca994834ae5c8cf07cba62a2",
"cellphone": "",
"city": "",
"country": "",
"email": "mail#foo.bar",
"fax": "",
"phone": 555,
...
},
"name": "...",
"account": {
"id": ...,
"uuid": "80b331f9e6644449bb3600b0e5145253",
"confirmed": true,
"profile": {
"id": ...,
"uuid": "e172bdcafe2645d7975852ca5685c98c",
"locale": "en",
"notifyMessage": false,
"notifyNews": true,
"notifyTask": true,
"timeZone": "Europe/Berlin"
},
"roleProfiles": {
"id": ..,
"uuid": "f1713758f3f2416faed3e68350f2d759",
"active": true,
"assemblies": [
{
"id": ..,
"uuid": "13d72449833a4eb0b5b4f62c729ee44f",
"image": "",
"commercialRegisters": [
123,
456
],
"contact": {
"id": ...,
"uuid": "bef3802297344e3c8c3619b6c91c345a",
"city": "",
"country": "",
...
},
"thumbnail": ""
},
{
...
}
],
},
"userName": "..."
},
"displayName": "...",
"firstName": "Foo",
"lastName": "Bar",
"salutation": "",
"title": ""
}
}
Hi references in your Java classes should be serialized to JSON as links and not as values.
This is how Spring REST does it.
The good thing is : That way you have a kind of lazy loading
The bad thing is that the client needs additional requests to get the values of the references.
I developed a complete solution for that, but that was a hard piece of work.
The client (in javascript) creates proxies for those references and resolves them on demand.
I have a demo of that at demo.appdriver.com
In the upper right corner you see a link 'REST API' click it and you can see the REST API of a rather complex domain model.
Now you can start to click on the user interface , create, change, delete etc.
and have a look at the traffic between client and server.
Hope it helps !