I'm using API Blueprint and Agilo to render my API documentation. When using enum type, I'm observing a weird behavior. The response is not shown with the defined enum value whereas the schema is showing all the enum values (which is expected) along with the declared value ('Monday'- Refer Actual) as well.
Data Structure section
# Data Structures
## Days (enum[string])
+ `Monday`
+ `Tuesday`
+ `Wednesday`
+ `Thursday`
## ListEntry
- playOrder: 1 (number)
- Id: 37a21975a499494f03367 (string)
- programDay: `Tuesday` (Days)
## `sample-request-200`
- id: 58828b2941cc351348 (string)
- startDate: `2019-08-01T11:00:00.000Z` (string)
- endDate: `2019-08-05T11:55:59.000Z` (string)
- Language: `en-US` (string)
- entries: ListEntry (array[object])
API Request Doc section
+ Request
+ Headers
Content-Type: application/json
+ Attributes (sample-request-200)
Actual
---- JSON Body ----
{
"playOrder": 1,
"Id": "37a21975a499494f03367",
"programDay": "Hello, world!" // Agilo shows "Hello,World" when some error occurred
}
-----Generated Schema-----
"programDay": {
"type": "string",
"enum": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Monday"
]
}
Desired
---- JSON Body ----
{
"playOrder": 1,
"Id": "37a21975a499494f03367",
"programDay": "Monday"
}
-----Generated Schema-----
"programDay": {
"type": "string",
"enum": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday"
]
}
Any idea on how to use the defined enum data structure in API blueprint (MSON). Not sure how to reference an enum value in the Object.
Is it right to use as below to reference an enum value?
- programDay: `Tuesday` (Days)
Structure:
# Data Structures
## Device (enum)
+ `mobile`
+ `desktop`
Use like this:
+ Request (multipart/form-data)
+ Attributes
+ `id`: abc (required)
+ `device` (Device)
Results:
Related
I have a Month model with a Date field:
class Month(models.Model):
month = models.DateField(primary_key=True, unique=True)
days = models.PositiveSmallIntegerField(default=0,
validators=IntegerValidators.MONTH_VALIDATOR, )
def __str__(self):
return str(self.month)
And it's serializer:
class MonthSerializer(serializers.ModelSerializer):
month = serializers.DateField(input_formats='%m-%Y', format='%m-%Y')
class Meta:
model = Month
fields = '__all__'
But when trying to send a request like this:
{
"month": "03-2020",
"days": 12
}
I get this 400 response:
{
"month": [
"Date has wrong format. Use one of these formats instead: %, m, -, %, Y."
]
}
I don't want to set this as default in my setting.
And when I make a request in the browsable API this format is saved:
[
{
"month": "07-2020",
"days": 23
},
{
"month": "07-2020",
"days": 22
}
]
input_formats expects an iterable, use input_formats=['%m-%Y'] instead.
Is it possible in the API Blueprint to define a set of possible responses for a given endpoint?
For example if I have a endpoint such as /movie/{id} I'd like to be able to define a set of movie records so that in the mock server I could GET /movie/1 or GET /movie/2 or GET /movie/3 and get the relevant record.
The examples I've seen all seem to define just one possible response.
You can add multiple request blocks, like this:
### Register [POST]
Registers an account
+ Request Already existing username
+ Body
{
"app": 3,
"username": "already-existing-username",
"password": "password"
}
+ Response 200 (application/json)
+ Body
{
"success": false,
"error": "The username specified is already registered to an account.",
"error_field": "username"
}
+ Request Invalid password
+ Body
{
"app": 3,
"username": "username",
"password": "password"
}
+ Response 200 (application/json)
+ Body
{
"success": false,
"error": "Please supply a valid password.",
"error_field": "password"
}
You can also find this in the official documentation
It's not possible to simulate this using a single action, but there is a workaround.
FORMAT: 1A
# Multi
## GET /movie/1
+ Response 200 (application/json)
{ "id": 1, "title": "First" }
## GET /movie/2
+ Response 200 (application/json)
{ "id": 2, "title": "Second" }
## GET /movie/3
+ Response 200 (application/json)
{ "id": 3, "title": "Third" }
## GET /movie/{id}
+ Parameters
+ id (required, number, `42`) ... Blah.
+ Response 200 (application/json)
{ "id": 42, "title": "First" }
Now, if you hit /movie/2, the mock server sends the appropriate response. Thanks.
this is how you provide multiple responses in your RAML file using Mulesoft(API designer) however if you're using mocking service for testing you'll always get the example response you set for testing
/{id}:
get:
headers:
Requester-Id:
required: true
responses:
200:
body:
application/json:
type: Account
example:
!include exapmle/AccountExample.raml
400:
body:
application/json:
example:
{"message":"Error retrieving account for the provided id"}
I am trying to call API and pass data to it from the form in my view to controller and then call API with post method.
What I get in params is:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"kLLaVRc6kcndkfB1nkntSTzGCg95CMCT1UvEncqwLgc=",
"score_sheet"=>{
"score_sheet_master"=>{
"issue_date(1i)"=>"2014", "issue_date(2i)"=>"6", "issue_date(3i)"=>"27"},
"print_date(1i)"=>"2014", "print_date(2i)"=>"6", "print_date(3i)"=>"27", "product_id"=>"2", "pull_id"=>"2", "press_run_id"=>"1", "total_section"=>"2",
"score_sheet_sections_attributes"=>{
"0"=>{"section_name"=>"A", "total_pages"=>"2", "color_pages"=>"1", "_destroy"=>"false"},
"1"=>{"section_name"=>"B", "total_pages"=>"1", "color_pages"=>"", "_destroy"=>"false"}},
"color_pages_rated"=>"1", "bw_pages_rated"=>"2", "foreman_id"=>"", "pic_id"=>""},
"score_sheet_master"=>{
"press_id"=>"1"},
"commit"=>"Create Score sheet"}
I want this Hash to be converted into the Following JSON which APIs accept. i-e.
{
"score_sheet": {
"score_sheet_master": {
"issue_date": "2014-06-25",
"press_id": "1"
},
"print_date": "2014-06-23",
"product_id": 1,
"pull_id": 2,
"press_run_id": 1,
"total_section": 2,
"score_sheet_sections_attributes": [
{
"section_name": "A",
"total_pages": 3,
"color_pages": "2,3",
"id": 9
},
{
"section_name": "B",
"total_pages": 1,
"color_pages": "1",
"id": 10
},
{
"section_name": "C",
"total_pages": 2,
"color_pages": "2"
}
],
"pic_id": 1,
"foreman_id": 1
}
}
Some the fields in JSON might be missing or may be more than the HASH but I don't have concern with that I will handle them personally the main issue is to convert this params Hash to the required JSON. Hold On I have implemented the date conversion thing that is working fine. but don't know how to convert score_sheet_sections_attributes array format to the required format.
Oh Got it myself:
sections = []
params["score_sheet"]["score_sheet_sections_attributes"].each {|k,v| sections << v}
params["score_sheet"]["score_sheet_sections_attributes"] = sections
Which gives:
{"utf8"=>"✓", "authenticity_token"=>"kLLaVRc6kcndkfB1nkntSTzGCg95CMCT1UvEncqwLgc=", "score_sheet"=>{"score_sheet_master"=>{"issue_date(1i)"=>"2014", "issue_date(2i)"=>"6", "issue_date(3i)"=>"27"}, "print_date(1i)"=>"2014", "print_date(2i)"=>"6", "print_date(3i)"=>"27", "product_id"=>"2", "pull_id"=>"2", "press_run_id"=>"1", "total_section"=>"2", "score_sheet_sections_attributes"=>[{"section_name"=>"A", "total_pages"=>"2", "color_pages"=>"1", "_destroy"=>"false"}, {"section_name"=>"B", "total_pages"=>"1", "color_pages"=>"", "_destroy"=>"false"}], "color_pages_rated"=>"1", "bw_pages_rated"=>"2", "foreman_id"=>"", "pic_id"=>""}, "score_sheet_master"=>{"press_id"=>"1"}, "commit"=>"Create Score sheet"}
and for dates I have another logic implemented and all done.
I have a django application with several views that accept json objects via POST requests. The json objects are medium-complex with a few layers of nesting, so I'm using the json library to parse raw_post_data, as shown here:
def handle_ajax_call(request):
post_json = json.loads(request.raw_post_data)
... (do stuff with json query)
Next, I want to write tests for these views. Unfortunately, I can't figure out how to pass the json object to the Client. Here's a simplest-case version of my code:
def test_ajax_call(self):
c = Client()
call_command('loadfixtures', 'temp-fixtures-1') #Custom command to populate the DB
J = {
some_info : {
attr1 : "AAAA",
attr2 : "BBBB",
list_attr : [ "x", "y", "z" ]
},
more_info : { ... },
info_list : [ 1, 22, 23, 24, 5, 26, 7 ]
}
J_string = json.dumps(J)
response = c.post('/ajax/call/', data=J_string )
When I run the test, it fails with:
AttributeError: 'str' object has no attribute 'items'
How can I pass the JSON object in the Client.post method?
The documentation seems to imply that if you pass a content_type parameter to client.post, it will treat the data value as a document and POST it directly. So try this:
response = c.post('/ajax/call/', content_type='application/json', data=J_string)
I am trying to send data to my controller from an ajax function that needs to have multiple levels, so something like this:
{
"lob": {
"TESTING": [
{
"name": "color",
"value": "1"
},
{
"name": "time",
"value": "2"
},
{
"name": "jeremy",
"value": "3"
},
{
"name": "fourtytwo",
"value": "4"
},
{
"name": "owl",
"value": "5"
},
{
"name": "why",
"value": "6"
},
{
"name": "derp",
"value": "7"
},
{
"name": "where",
"value": "8"
}
]
}
}
but when it sends to grails I am getting this when I print out the params
[lob[TESTING][4][value]:5,
lob[TESTING][3][name]:fourtytwo,
lob[TESTING][6][name]:derp,
lob[TESTING][5][name]:why,
lob[TESTING][3][value]:4,
lob[TESTING][1][value]:2,
lob[TESTING][2][value]:3,
lob[TESTING][5][value]:6,
lob[TESTING][1][name]:time,
lob[TESTING][0][value]:1,
lob[TESTING][6][value]:7,
lob[TESTING][0][name]:color,
lob[TESTING][7][value]:8,
lob[TESTING][4][name]:owl,
lob[TESTING][7][name]:where,
lob[TESTING][2][name]:jeremy,
action:save,
controller:LOB]
The data I am sending from JavaScript:
{
lob: {
TESTING: $form.serializeArray()
}
}
I have been reading multiple forums saying using JSON.parse or request.JSON but these solutions do not seem to be fixing my problems. I want to be able to access the data like
params.lob.testing.each{ a->
println a
}
I will be doing alot more than just that but it would be nice to be able to access the data in that fashion. I am using Grails 2.1 and Jquery 1.7.2
Actually Grails makes it very easy. I've taken your test data and ran it through the following:
import grails.converters.JSON
class LobController {
def save = {
def json = request.JSON
json.lob.TESTING.each {item->
println "Name: ${item.name} - Value: ${item.value}"
}
//render something back if you need to here
}
}
And it outputs:
Name color - Value: 1
Name time - Value: 2
Name jeremy - Value: 3
Name fourtytwo - Value: 4
Name owl - Value: 5
Name why - Value: 6
Name derp - Value: 7
Name where - Value: 8
I created a UrlMapping entry like this (you probably already have this):
"/myApi"(controller: "lob", parseRequest: true) {
action = [POST: "save"]
}
The parseRequest: true will automatically parse the incoming JSON.
I found a `serializeJSON' function that might replace the serializeArray() to format this for JSON. The following was provided by Arjen Oosterkamp on the jQuery serializeArray page:
(function( $ ){
$.fn.serializeJSON=function() {
var json = {};
jQuery.map($(this).serializeArray(), function(n, i){
json[n['name']] = n['value'];
});
return json;
};
})( jQuery );
Simply use as $('form').serializeJSON();
All credit for that function goes to Arjen Oosterkamp...