Describing relationships in JSON Schema so that Paw can generate payload - jsonschema

JSON Schema Faker can generate a JSON payload automatically from a JSON Schema. I found some documentation about it on https://github.com/luckymarmot/Paw-JSONSchemaFakerDynamicValue#-faker-api-reference
But there is still one thing I can't figure out how to do: some of the fields in my JSON are references to ids of other elements in the same JSON:
{
"trainings":[
{
"title": "English Training",
"topic": "1234"
}
],
"topics": [
{
"id":"1234",
"title":"Languages"
}
]
}
training.topic must be the same as one topics.id.
Maybe there is a way to describe that kind of relationship in JSON Schema but I couldn't find any documentation about it, just some doc about how to reference and reuse JSON schema elements. But most likely there must be a way to describe is in Faker syntax.

Related

How to use array type for expect response body in RESTinstance for Robot Framework

I am writing Robot tests for API endpoint which returns a response body of an array of objects. I am using RESTinstance to validate the response body.
I have the JSON schema for the individual object.
How does one validate an array of that JSON schema?
I tried these but it didn't work:
Expect Response Body Array ${schema}/alert.json
Expect Response Body [${schema}/alert.json]
I then created a new schema alerts.json which simply is an array of the object schema:
{
"type": "array",
"items": {
"$ref": "file:../schema/alert.json"
}
}
and tried
Expect Response Body [${schema}/alerts.json]
This threw a RefResolutionError for a $ref contained in the alert.json object.
None of these solutions worked
Is there a standard way to achieve this using Robot and REST?
Thanks

RestKit: Composing Relationships with the Nil Key Path

I have two classes
Author with attributes id, papers (Paper relationship), ...
Paper with attributes id, mainAuthor (Author relationship), authors (Author relationship) ...
and want to map some JSON to it
"authors": [
{
"id": 123,
"papers": [
{
"id": 1,
"main_author_id": 123,
...
},
...
]
},
...
]
The problem is that the JSON is not structured like
"authors": [
{
"id": 123,
"papers": [
{
"id": 1,
"main_author": {
"id": 123
}
...
},
...
]
},
...
]
so that I could easily map things (note the *main_author* part of both JSON examples). I tried using mapping this value without a key path as explained here:
[authorMapping addAttributeMappingToKeyOfRepresentationFromAttribute:#"main_author_id"];
[authorMapping addAttributeMappingsFromDictionary:#{#"(main_author_id)": #"id"}];
but I'm getting an error telling me that the keyPath id already exists and I may not add a second mapping for this keyPath. I totally understand this error, but I have no idea how to map from *main_author_id* back to id. Changing the data source may be the best solution, but this is unfortunately not possible.
Any suggestion is highly welcome! Thanks!
This is exactly what foreign key mapping is for. It allows you to temporarily store the 'identity' value that you're provided with and then RestKit will find the appropriate object and complete the relationship.
Apart from the Answer #Wain (foreign key mapping) provided, it is also possible to implement a custom serialization (c.f. RKSerialization) and modify the objects before mapping takes place. However, the aforementioned method is superior to this (somehow ugly) solution.

RestKit Dynamic nested mapping

I see that the restkit document is quite nice and has variety of examples on object modelling. There is also an example of nested mapping but I find my scenario little bit different than this. RestKit documentation provides the example mapping of the nested attribute with the following json format.
Sample JSON structure from the RestKit Documentation :
{
"blake": {
"email": "blake#restkit.org",
"favorite_animal": "Monkey"
},
"sarah": {
"email": "sarah#restkit.org",
"favorite_animal": "Cat"
}
}
Suppose that my json is a bit different as this;
My JSON structure :
{
"id" : 1,
"author" : "RestKit",
"blake": {
"email": "blake#restkit.org",
"favorite_animal": "Monkey"
},
"sarah": {
"email": "sarah#restkit.org",
"favorite_animal": "Cat"
}
}
I created two different managedobject model with the following attributes and to many relations.
Two different entities for my structure Product and creator to map the above JSON object.
Product Creator
identifier <------------------- >> name
author email
favouriteAnimal
Now, my mapping would look like this for Product model would be;
This is how I map the Product entity,
[mapping mapKeyPath:"id" toAttribute:"identifier"];
[mapping mapKeyPath:"author" toAttribute: "author"];
But note here, mapping the nested dictionary attribute does not work for me.
// [mapping mapKeyOfNestedDictionaryToAttribute:#"creators"];
Now, in the authors class.
I could not figure out the usual way to map the above JSON structure.
If you have control over the web service, I would strongly recommend reorganizing your response data like this:
{
product:
{
id: 1,
author: 'RestKit',
creators: [
{
id: 1,
name: 'Blake',
email: '...',
favorite_animal: 'Monkey'
},
{
id: 2,
name: 'Sarah',
email: '...',
favorite_animal: 'Cat'
}
]
}
}
Following this structure, you'd be able to use RestKit's nested mapping features, and the relationship would be correctly reflected in the deserialized objects received by the object loader delegate. RestKit relies on naming and structure standards to simplify the code required to achieve the task. Your example deviates from key-value coding standards, so RK doesn't provide an easy way to interact with your data format.
If you don't have access or you can't change it, I think you'll need to map known key-value pairs with a mapping and perform the remaining assignments with a custom evaluator. You'd need to assume the unknown keys are actually name values for associated creators and their associated values contain the attribute hash for each. Using that, you'd then reconstruct each object manually.

RestKit: Map single object into existing array

I have the following JSON structure which i get from a RestService:
{
"customer": {
"id": "123456",
[more attributes ....]
"items": [
{
"id": "1234",
},
{
"id": "2345",
}
[more items...]
]
}
}
which i successfully map into Core Data using RestKit. From another RestService (which i can not change) i then get more details to one single item in the items array. the JSON answer looks like
{
"customer": {
"id: "123456",
"item": {
"id": "1234",
"name": "foo",
[other attributes...]
}
}
}
Now the question: How can i map the second answer, so that the single item is added to the items array (or updated if it is already in there)?
Thanks for any ideas!
If you already know how to map JSON to Core Data, all that's left is just fetch theobject you want to add your item attributes to(using id or something else) and then just set it,rewriting the old one,or adding new fields.That's just general approach
If you set the appropriate primaryKeyAttribute of the RKManagedObjectMapping object you should be able to perform the mapping as you want it to.
It would actually be easier to help you, if you would post some of your mapping code, but this is how I meant it to be
Create the mapping for your customer object, defining all possible attributes and declare the mappingObject.primaryKeyAttribute = #"id"
Execute the mapping with the first request (or first answer as you put it)
After the first mapping step is finished execute the second request
This should initially create the customer objects you want and then update them.

Is RestKit the only framework that has JSON to Objective-C objects mapping?

I am looking for a library or framework that does JSON to Objective-C relational object mapping.
i.e. I need to map JSON containing objects, array of objects and dictionaries of objects to my custom objects.
something like:
DataObject {
"user" : {
"name":"Peter",
"id":1234
}
"place": "UK"
"job": {
"title" : "CTO",
"salary" : 1234567
}
"employess": [
{
"name":"Carlton",
"id":1235
},
{
"name":"Hugo",
"id":12346
}]
}
So there is a DataObject a UserObject and an employees array consisting of UserObjects.
I would like for the mapping from the JSON to my DataObject to happen "automatically", of course meant as I would like to describe the objects and there relations in the Object class and have the mapping done from this, instead of manually mapping each nested object.
(First level native objective-c properties are easily done with setValue:forKey and other KVO methods, but from there on it gets complicated).
I have been testing out RestKit but it seems there is no way to pick and choose which functionality you need from that framework, it is either all of it or none of it, and I do find it does too much for my needs.
Are anyone familiar with a library etc. out there that can do this?
Thank you in advance.
To map JSON to Objective-C objects, I have tried RestKit. I used it a while ago, so my criticisms might not apply anymore.
What I found out: nice idea. Not too complicated to plug-in. If it works, great for you. But if not, or if you need to push it a bit further, good luck to debug.
I regret the time I invested in it.
I am only looking for JSON to Objective-C objects, not the other way around.
I found a link on SO to JTObjectMapping - but can't find the original answer. Seems more lightweight and close to what I was searching, but I did not had the opportunity to try it.
An other similar class: jastor.
I prefer the approach of this two classes over RestKit, as it only takes care of one job, whereas RestKit tried to handle everything.
What you have posted above isn't valid JSON. If you made it valid JSON what you want to do is impossible without a specific schema, eg.
{
"DataObject": {
"user": {
"name": "Peter",
"id": 1234
},
"place": "UK",
"job": {
"title": "CTO",
"salary": 1234567
}
}
}
Is Dataobject a dictionary or an Object? What about User or Job? What is User is an instance of NSUser and job is an NSDictionary?
On the other hand, if you have a known schema:-
[
{
"class": "DataObject",
"properties": {
"user": {
"class": "User",
"properties": {
"name": "Peter",
"id": 1234
}
},
"place": "UK",
"job": {
"title": "CTO",
"salary": 1234567
}
}
}
]
you don't need a framework as it is trivial to map to your objects yourself once you have valid JSON. Pseudocode:-
createWithDict(dict) {
var newOb = create new(dict["class"]);
dict.properties.each( val, key ) {
if(val is dictionary && val.hasproperty("class"))
val = createWithDict(val)
newOb[key] = val
}
return newOb;
}