I'm building an app that talks to an existing REST API. That API was built using a framework called Jackson, I believe, and I thought that I might use RestKit to handle the object creation of objects used by the API. However, I've run into a problem, Jackson likes to send and get JSON that contains structures like this: {"#id": 1, "id": 4} but RestKit chokes on "#id" with a "not key value coding-compliant for the key" exception.
Changing the existing API is going to be an uphill struggle, but I'm wondering if I can shim some sort of conversion that replaces "#id" with a legal key, like "AT__id" on incoming JSON and does the opposite conversion on outgoing JSON. My problem is that I'm new to RestKit and don't know where to begin. I'm contemplating tracing code to see where I might modify the code, but is anyone familiar enough with how it is structured to offer suggestions for where to begin and save me the effort?
I discovered that "#id" is a Jackson convention, not a requirement. We tested by changing it to something that conforms to the lowercase/ascii rule and it worked out perfectly. We'll change it for the next server update. This doesn't answer the question, but does solve the immediate problem.
Related
I'd like to use a personnal API for named entity recognition (NER), and use brat for visualisation. It seems brat offers an Automatic annotation tool, but documentation about its configuration is sparse.
Are there available working examples of this features ?
Could someone explain me what should be the format of the response of the API ?
I finally manage to understand how it works, thanks to this topic in the GoogleGroup diffusion list of BRAT
https://groups.google.com/g/brat-users/c/shX1T2hqzgI
The text is sent to the Automatic Annotator API as a byte string in the body of a POST request, and the format BRAT required in response from this API is in the form of a dictionary of dictionaries, namel(
{
"T1": {
"type": "WhatEverYouWantString", # must be defined in the annotation.conf file
"offsets": [(0, 2), (10, 12)], # list of tuples of integers that correspond to the start and end position of
"texts": ["to", "go"]
}
"T2" : {
"type": "SomeString",
"offsets":[(start1, stop1), (start2, stop2), ...]
"texts":["string[start1:stop1]", "string[start2:stop2]", ...
}
"T3" : ....
}
THEN, you put this dictionary in a JSON format and you send it back to BRAT.
Note :
"T1", "T2", ... are mandatory keys (and corresponds to the Term index in the .ann file that BRAT generates during manual annotation)
the keys "type", "offsets" and "texts" are mandatory, otherwise you get some error in the log of BRAT (you can consult these log as explained in the GoogleGroup thread linked above)
the format of the values are strict ("type" gets a string, "offsets" gets a list of tuple (or list) or integers, "texts" gets a list of strings), otherwise you get BRAT errors
I suppose that the strings in "texts" must corresponds to the "offsets", otherwise there should be an error, or at least a problem with the display of tags (this is already the case if you generate the .ann files from an automatic detection algorithm and have different start and stop than the associated text)
I hope it helps. I managed to make the API using Flask this morning, but I needed to construct a flask.Response object to get the correct output format. Also, the incoming format from BRAT to the Flask API could not be catch until I used a flask.request object with request.get_body() method.
Also, I have to mention that I was not able to use the examples given in the BRAT GitHub :
https://github.com/nlplab/brat/blob/master/tools/tokenservice.py
https://github.com/nlplab/brat/blob/master/tools/randomtaggerservice.py
I mean I could not make them working, but I'm not familiar at all with API and HTTP packages in Python. At least I figured out what was the correct format for the API response.
Finally, I have no idea how to make relations among entities (i.e. BRAT arrows) format from the API, though
https://github.com/nlplab/brat/blob/master/tools/restoataggerservice.py
seems to work with such thing.
The GoogleGroup discussion
https://groups.google.com/g/brat-users/c/lzmd2Nyyezw/m/CMe9FenZAAAJ
seems to mention that it is not possible to send relations between entities back from the Automatic Annotation API and make them work with BRAT.
I may try it later :-)
I am facing problem with the query parameters if they are in camelCase format.
for ex : http://localhost:9000/api/hello?personName=test
This format doesnt work with the Swagger UI. Swagger is not able to pickup any parameter defined in camelCase. It shows error "missing required params: presonName".
Hope this is clear now.
Adding one more screen shot with error
thanks
Wierd but true. I ended up finding something which is a very rare case. As you can see in the screen shot, I was using nodeType as a parameter and to my surprise, the word nodeType is a reserved word in "document" object of html. and thats the reason it creates a problem. I just changed the nodeType to nodeTypeStr and it works fine for me. But still it will be good if Swagger developers take care of handling the reserved words.
I am building an iOS app, and I am using RestKit v0.20 for mapping a JSON file.
The JSON file structure is the next:
{
"artists":{
"#total":"100",
"#page":"1",
"#itemsPerPage":"30",
"artist":[
{
"#sortName":"Ai Phoenix",
"#name":"Ai Phoenix",
"#mbid":"ffb0ac71-a438-4fce-91a5-58041aba0135",
"url":"http:\/\/www.setlist.fm\/setlists\/ai-phoenix-13d78159.html"
},
{
"#sortName":"Phoenix",
"#name":"Phoenix",
"#mbid":"02f4c1ff-65e0-4412-8e8b-6239b0faecb5",
"url":"http:\/\/www.setlist.fm\/setlists\/phoenix-53d653f9.html"
}
]
}
I don't know how to map these attributes that have the prefix "#" (#sortname, #name, #mbid). I have tried to map as a normal field (#"#name", #"#mbid", ...) and it fails. In the other hand, #"url" is working well for the "url" field. I have searched and all I have got is that this notation is because of a translation from a XML file, called Badgerfish.
I this could help, have got the correspondant XML to this JSON file:
<artists total="100" page="1" itemsPerPage="30">
<artist sortName="Ai Phoenix" name="Ai Phoenix" mbid="ffb0ac71-a438-4fce-91a5- 58041aba0135">
<url>
http://www.setlist.fm/setlists/ai-phoenix-13d78159.html
</url>
</artist>
If anybody can help me, I would appreciate it. Thanks everybody!
This is a known limitation of RestKit.
Quoting the framework's author himself:
This is a known limitation and a consequence of RestKit's reliance on
Cocoa's key-value coding system for property access. The '#' prefix is
reserved for denominating key-value collection operators.
You are going to need to change that JSON format to effectively work
with RestKit
As far as I know RESTKit use KVC, and # is used by KVC so can't use it in the JSON key names. Try to check if can change the # prefix with something else, such as "m_".
If you're not using key paths for mapping another alternative might be to create a private RestKit branch and use objectForKey: and relatives instead of valueForKey:. In an iOS application you have to ship your own copy of RestKit anyway. (Did this for my simple app, and it works so far)
I have problem getting statistics information from youtube data api. I make a request to http://gdata.youtube.com/feeds/api/videos?q=video_id&alt=json, it works for some, but for some video id, the response does not contain 'entry', 'yt$statistics', 'gd$rating' for example:
zLcbznigfs missing 'entry', aVfN6XjACDY missing 'yt$statistics', fjhQ9Kf4iHk missing 'gd$rating'
After moving around, i found out the solution for this: use &alt=atom instead of using &alt=json, which means that we better read from Atom feed than JSON (and feedparser is an excellent module for doing this). I have checked this with several video id, it works fine.
Hope that help. Thanks.
I'm working on an API that accepts data from remote clients, some of which where the key in an HTTP POST almost functions as an array. In english what this means is say I have a resource on my server called "class". A class in this sense, is the type a student sits in and a teacher educates in. When the user submits an HTTP POST to create a new class for their application, a lot of the key value pairs look like:
student_name: Bob Smith
student_name: Jane Smith
student_name: Chris Smith
What's the best way to handle this on both the client side (let's say the client is cURL or ActiveResource, whatever..) and what's a decent way of handling this on the server-side if my server is a Ruby on Rails app? Need a way to allow for multiple keys with the same name and without any namespace clashing or loss of data.
My requirement has to be that the POST data is urlencoded key/value pairs.
There are two ways to handle this, and it's going to depend on your client-side architecture how you go about doing it, as the HTTP standards do not make the situation cut and dry.
Traditionally, HTTP requests would simply use the same key for repeated values, and leave it up to the client architecture to realize what was going on. For instance, you could have a post request with the following values:
student_name=Bob+Smith&student_name=Jane+Smith&student_name=Chris+Smith
When the receiving architecture got that string, it would have to realize that there were multiple keys of student_name and act accordingly. It's usually implemented so that if you have a single key, a scalar value is created, and if you have multiples of the same key, the values are put into an array.
Modern client-side architectures such as PHP and Rails use a different syntax however. Any key you want to be read in as an array gets square brackets appended, like this:
student_name[]=Bob+Smith&student_name[]=Jane+Smith&student_name[]=Chris+Smith
The receiving architecture will create an array structure named "student_name" without the brackets. The square bracket syntax solves the problem of not being able to send an array with only a single value, which could not be handled with the "traditional" method.
Because you're using Rails, the square bracket syntax would be the way to go. If you think you might switch server-side architectures or want to distribute your code, you could look into more agnostic methods, such as JSON-encoding the string being sent, which adds overhead, but might be useful if it's a situation you expect to have to handle.
There's a great post on all this in the context of JQuery Ajax parameters here.
Send your data as XML or JSON and parse whatever you need out of it.