How to map root dictionaries using RestKit? - objective-c

I've just started using RestKit. Given the JSON structure below, how do I configure an object mapping for key 1 and key 2? I've successfully set up the object mapping for key 3.
{
"key 1": "value",
"key 2": "value",
"key 3": [
{
"key": "value"
"key": "value"
},
{
"key": "value"
"key": "value"
},
]
}
Thanks in advance.

To successfully use the RestKit object mapping without KVC you'll need to use two mappings - one inner mapping for the "key 3" and one outer mapping for "key 1" and "key 2".
You then define a relationship for the "key 3" key path. See another question for details.

Related

How to get real data types and allowed values of fields for a defect

On using the typedef() method from pyral(version - 1.4.2) library, I am able to get the fields for the respective artifacts types(eg. defect),
but in the response -> the data type (attribute type) for the fields differs from the one seen on the UI. eg. for drop-down field I'm getting 'Rating/String' as AttributeType instead of 'DROP_DOWN'.
how could I get the real data type as the one seen on UI through the response?
Is there any other api that I can use to get all the fields and there datatype, allowed values attributes for a defect?
If you take a look at the WSAPI docs, you'll find that the AttributeDefinition object has many different elements. The AttributeType is the one you're accessing which can be one of the following values:
"BINARY_DATA", "BOOLEAN", "COLLECTION", "DATE", "DECIMAL", "INTEGER", "OBJECT", "QUANTITY", "RATING", "RAW", "STATE", "STRING", "TEXT", "MAP", "WEB_LINK"
But it also has an element called RealAttributeType which can be one of the following values:
"BINARY_DATA", "OBJECT", "QUANTITY", "RATING", "STATE", "RAW", "COLLECTION", "TEXT", "BOOLEAN", "INTEGER", "DECIMAL", "WEB_LINK", "DATE", "STRING", "DROP_DOWN", "MULTI_VALUE", "USER"
Have you tried accessing the RealAttributeType to see its value?

How to extract the field from JSON object with QueryRecord

I have been struggling with this problem for a long time. I need to create a new JSON flowfile using QueryRecord by taking an array (field ref) from input JSON field refs and skip the object field as shown in example below:
Input JSON flowfile
{
"name": "name1",
"desc": "full1",
"refs": {
"ref": [
{
"source": "source1",
"url": "url1"
},
{
"source": "source2",
"url": "url2"
}
]
}
}
QueryRecord configuration
JSONTreeReader setup as Infer Schema and JSONRecordSetWriter
select name, description, (array[rpath(refs, '//ref[*]')]) as sources from flowfile
Output JSON (need)
{
"name": "name1",
"desc": "full1",
"references": [
{
"source": "source1",
"url": "url1"
},
{
"source": "source2",
"url": "url2"
}
]
}
But got error:
QueryRecord Failed to write MapRecord[{references=[Ljava.lang.Object;#27fd935f, description=full1, name=name1}] with schema ["name" : "STRING", "description" : "STRING", "references" : "ARRAY[STRING]"] as a JSON Object due to java.lang.ClassCastException: null
Try the following approach, in your case it shoud work:
1) Read your JSON field fully (I imitated it with GenerateFlowFile processor with your example)
2) Add EvaluateJsonPath processor which will put 2 header fileds (name, desc) into the attributes:
3) Add SplitJson processor which will split your JSON byt refs/ref/ groups (split by "$.refs.ref"):
4) Add ReplaceText processor which will add you header fields (name, desc) to the split lines (replace "[{]" value with "{"name":"${json.name}","desc":"${json.desc}","):
5) It`s done:
Full process in my demo case:
Hope this helps.
Solution!: use JoltTransformJSON to transform JSON by Jolt specification. About this specification.

What properties of an item should be included in the json schema?

I am confused about for which situation I am defining the properties in my json schemas.
Assume I have an item product for which I am trying to define a schema. In my database the products table has id, brand_id, name, item_number and description. All except description are required fields. The id is autogenerated by the database and the brand_id is set upon creation automatically by the api based on the user creating.
This means I can POST /api/products using only the following data:
{
"product": {
"name": "Product Name",
"item_number": "item001"
}
}
However, how should I now define the product schema? Should I include the properties id and brand_id? If so, should I label them as required, even though they are set automatically?
This is what I came up with:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://jsonschema.net/products",
"type": "object",
"properties": {
"item_number": {
"id": "http://jsonschema.net/products/item_number",
"type": "string"
},
"name": {
"id": "http://jsonschema.net/products/name",
"type": "string"
},
"description": {
"id": "http://jsonschema.net/products/description",
"type": "string",
"default": "null"
}
},
"required": [
"item_number",
"name"
]
}
You should only define in your JSON schema properties that are dealt with by the user of the API.
In your case, it makes no sense to have id and brand_id in the schema that defines the POST body entity for the creation of a new product because these values are not provided by the API user.
This said, you may have another schema for existing product entities where these two fields are present, if it's OK to expose them publicly.
If that's the case, for this you can use schema union mechanism and have the "existing product" schema use allOf new_product.json and add id and brand_id to it.

How to get list of statements for a given Wikidata ID?

The only thing I managed to do is this link:
https://www.wikidata.org/w/api.php?action=wbgetentities&ids=Q568&format=jsonfm
But this produces lots of useless data. What I need is to get all the statements for the given item, but I can't see any of the statements in the query above.
here it will be:
{ "instance of" : "chemical element",
"element symbol" : "Li",
"atomic number" : 3,
"oxidation state" : 1,
"subclass of" : ["chemical element", "alkali metal"]
// etc...
}
Is there an API for this or must I scrape the web page?
The information you want is in your query, except it's hard to decode. For example, this:
"P246": [
{
"id": "q568$E47B8CE7-C91D-484A-9DA4-6153F132997D",
"mainsnak": {
"snaktype": "value",
"property": "P246",
"datatype": "string",
"datavalue": {
"value": "Li",
"type": "string"
}
},
"type": "statement",
"rank": "normal",
"references": …
}
]
means that the “element symbol” (property P246) is “Li”. So, you will need to read all the properties from your query and then find out the name for each of the properties you found.
To get just the statements, you could also use action=wbgetclaims, but it's in the same format as above.

Restkit to-many relationship append to set instead of setting a new set

I have a iOS Restkit related question. I have a parent-child relationship data coming from a remote server and map those object to a NSManagedObject object with Restkit. The problem that I am currently having is every request to the server always wipe out the "child" relationship and replace it with the new data coming from the server. Is there a way to avoid those and append the new child instead?
For example: I have a classic Category --> Products relationship.
{"categories": [
{
"cat_id": "1",
"cat_title": "category 1",
"cat_tag": 1,
"product": [
{
"prod_id": "1",
"prod_name": "product 1",
"prod_tag": 1
},
{
"prod_id": "2",
"prod_name": "product 2",
"prod_tag": 1
}
]
}
] }
And that works fine and everything is saved properly with the relationship on the CoreData. But if I make another request to the server and have a new response:
{"categories": [
{
"cat_id": "1",
"cat_title": "category 1",
"cat_tag": 1,
"product": [
{
"prod_id": "3",
"prod_name": "product 3",
"prod_tag": 1
},
{
"prod_id": "4",
"prod_name": "product 4",
"prod_tag": 1
}
]
}
] }
I will have product 3 and product 4 replace product 1 and product 2 on the database. I am sure I setup all the relationship and primary key correctly. (Both cat_id and prod_id are set as a primary key).
Having investigated through the RestKit's internal framework, I noticed that around line 576 in the RKObjectMappingOperation class, there is
RKLogTrace(#"Mapped NSSet relationship object from keyPath '%#' to
'%#'. Value: %#", relationshipMapping.sourceKeyPath,
relationshipMapping.destinationKeyPath, destinationObject);
NSMutableSet *destinationSet = [self.destinationObject
mutableSetValueForKey:relationshipMapping.destinationKeyPath];
[destinationSet setSet:destinationObject];
So I guess that is easy to just change
[destinationSet setSet:destinationObject];
to
[destinationSet addObjectsFromArray:[destinationObject allObjects]]
But I was wondering whether there is a better way to do it?
Cheers,
Thanks for the support from Reskit. It is now supported by RKRelationshipMapping.(https://github.com/RestKit/RestKit/issues/989)
Just set assignmentPolicy value of RKRelationshipMapping instance to RKUnionAssignmentPolicy