- Notifications
You must be signed in to change notification settings - Fork90
Fake JSON Server is a Fake REST API that can be used as a Back End for prototyping or as a template for a CRUD Back End.
License
ttu/dotnet-fake-json-server
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Build server | Platform | Build status |
---|---|---|
Travis | Linux / macOS | |
CircleCI | Windows |
Fake JSON Server is a Fake REST API that can be used as a Back End for prototyping or as a template for a CRUD Back End. Fake JSON Server also has an experimental GraphQL query and mutation support.
- No need to define types for resources, uses dynamic typing
- No need to define routes, routes are handled dynamically
- No database, data is stored to a single JSON file
- No setup required, just start the server and API is ready to be used with any data
- API is built following the best practices and can be used as a reference when building your own API
- Contains all common features used with well functioning APIs (see features listed below)
- Can be run on Windows, Linux and macOS without any installation or prerequisites from executable or with Docker
https://ttu.github.io/dotnet-fake-json-server/
- Supported HTTP methods#
- All methods for CRUD operations (GET, PUT, POST, PATCH, DELETE)
- Methods for fetching resource information (HEAD,OPTIONS)
- Async versions of update operations with long running operations and queues#
- REST API follows best practices from multiple guides
- Uses correct Status Codes, Headers, etc.
- As all guides have slightly different recommendations, this compilation is based on our opinions
- Paging, filtering, selecting, text search etc.#
- Token, Basic and API key Authentication#
- WebSocket update notifications#
- Simulate delay and errors for requests#
- Static files#
- Swagger#
- CORS#
- Content Negotiation (output formatsJSON,CSV andXML)#
- Caching and avoiding mid-air collisions with ETag#
- Configurable custom response transformation#
- Experimental GraphQL query and mutation support#
- .NET 8
- ASP.NET Core
- Data is stored to a JSON-file withJSON Flat File Data Store
Click to here to see contents
- Get started
- Examples
- Features
- Routes, Functionalities and Examples
- Collections and objects
- Routes
- Identifiers
- HTTP return codes
- Data Store Id-field name
- Eager data reload
- Reload
- Health Check
- Guidelines
- Other Links
- Releases
- Changelog
- Contributing
- License
# Get source code from GitHub$ git clone https://github.com/ttu/dotnet-fake-json-server.git$cd dotnet-fake-json-server/FakeServer$ dotnet run
Start server with defined data-file and url (optional arguments)
# Optional arguments:# --file <FILE> Data store's JSON file (default datastore.json)# --urls <URL> Server url (default http://localhost:57602)# --serve <PATH> Serve static files (default wwwroot)# --version Prints the version of the app$ dotnet run --file data.json --urls http://localhost:57602
Server can be installed as adotnet global tool. Settings files are then located at%USERPROFILE%\.dotnet\tools
(Windows) and$HOME/.dotnet/tools
(Linux/macOS). By default data stores's JSON file will be created to execution directory.
# install as a global tool$ dotnet tool install --global FakeServer# Example: Start server$ fake-server --file data.json --urls http://localhost:57602# Update to the newest version$ dotnet tool update --global FakeServer
If you don't have .NET installed, you can run the server with Docker.
# Get source code from GitHub$ git clone https://github.com/ttu/dotnet-fake-json-server.git$cd dotnet-fake-json-server$ docker build -t fakeapi.# Run in foreground$ docker run -it -p 57602:57602 --name fakeapi fakeapi# Run in detached mode (run in background)$ docker run -it -d -p 57602:57602 --name fakeapi fakeapi# Start stopped container (remove -a to run in background)$ docker start -a fakeapi
Copy JSON-file to/from container. Filename isdatastore.json
# Copy file from host to container$ docker cp datastore.json fakeapi:/app/datastore.json# Copy file from container to host$ docker cp fakeapi:/app/datastore.json datastore.json
The self-contained application archive contains Fake JSON Server, .NET runtime and all required third-party dependencies.No installation or prerequisites are needed.
- Go toLatest Release
- Download correct archive matching your OS
- Extract files and execute
E.g. download and execute version0.11.0 formacOS
$ mkdir FakeServer&&cd FakeServer$ wget https://github.com/ttu/dotnet-fake-json-server/releases/download/0.11.0/fakeserver-osx-x64.tar.gz$ tar -zxvf fakeserver-osx-x64.tar.gz$ chmod +x FakeServer$ ./FakeServer
Fake Server can serve static files. Location of files can be absolute or relative to the current location.
$ dotnet run -s/--serve [fullpath/relative path]# e.g.$ dotnet run -s build# Use Fake Server as a global tool$ fake-server -s/--serve [fullpath/relative path]]# e.g.$ fake-server --serve c:\temp\react_app\build$ fake-server --serve /home/user/app/dist$ fake-server --serve ./build
When user defines static files, it is assumed that user is serving a single page app and then REST API is not working. If API is needed, start other instance of Fake Server.
# List collections (should be empty, if data.json didn't exist before)$ curl http://localhost:57602/api# Insert new user$ curl -H"Content-type: application/json" -X POST -d'{ "name": "Phil", "age": 20, "location": "NY" }' http://localhost:57602/api/users/# Insert another user$ curl -H"Content-type: application/json" -X POST -d'{ "name": "James", "age": 40, "location": "SF" }' http://localhost:57602/api/users/# List users$ curl http://localhost:57602/api/users# List users from NY$ curl http://localhost:57602/api/users?location=NY# Get User with Id 1$ curl http://localhost:57602/api/users/1# ...# Add users to data.json manually# Get all users$ curl http://localhost:57602/api/users/# ...# Or open url http://localhost:57602/swagger/ with browser and use Swagger
Redux TodoMVC example modified to use Fake JSON Server as a Back End.
Example queries are available inPostman workspace format inFakeServer_Workspace.json. These queries can be used inPostman,Insomnia,Yaak, and similar tools.
Fake REST API supports Token and Basic authentication and API keys.
Authentication can be disabled fromappsettings.json
by setting Enabled tofalse
.AuthenticationType
options aretoken
,basic
andapikey
.
Add allowed usernames/passwords toUsers
-array. Add optional API key toApiKey
-property.
"Authentication": {"Enabled":true,"AuthenticationType":"token","Users": [ {"Username":"admin","Password":"root" } ],"ApiKey":"abcd1234"}
API has a token provider middleware which provides an endpoint for token generation/token
. Endpoint supports'content-type: multipart/form-data
andcontent-type: application/json
. Username and password must be inusername
andpassword
fields.
Get token:
# content-type: multipart/form-data$ curl -X POST -H'content-type: multipart/form-data' -F username=admin -F password=root http://localhost:57602/token# content-type: application/json$ curl -X POST -H'content-type: application/json' -d'{ "username": "admin", "password": "root" }' http://localhost:57602/token
Token can be fetch also usingClient Credentials
grant type (see example from Insomnia workspace):
$ curl -X POST -d"grant_type=client_credentials&client_id=admin&client_secret=root" http://localhost:57602/token
Add token to Authorization header:
$ curl -H'Authorization: Bearer [TOKEN]' http://localhost:57602/api
Token authentication supports logout functionality. By design, tokens do not support token invalidation and logout is implemented by blacklisting tokens.
$ curl -X POST -d'' -H'Authorization: Bearer [TOKEN]' http://localhost:57602/logout
The implementation is quite similiar to SimpleTokenProvider and more info on that can be found fromGitHub andStormPath's blog post.
NOTE: It is not recommended to use Basic Authentication in production as base64 is a reversible encoding
Add base64 encoded username:password to authorization header e.g.'Authorization: Basic YWRtaW46cm9vdA=='
.
$ curl -u admin:root http://localhost:57602/api# -u argument creates Authorization header with encoded username and password$ curl -H'Authorization: Basic YWRtaW46cm9vdA==' http://localhost:57602/api
Add key set to Authentication settings toX-API-KEY
header e.g.X-API-KEY: abcd1234'
.
$ curl -H'X-API-KEY: abcd1234' http://localhost:57602/api
API will send the latest update's method (POST, PUT, PATCH, DELETE
), path, collection and optional item id with WebSocket.
{"method":"PATCH","path":"/api/users/2","collection":"users","itemId":2 }
wwwroot\index.html has a WebSocket example.
CORS is enabled and it allows everything.
GET /
Returns static files from wwwroot or defined location. Default file isindex.html
.
Checkhow to serve static files from defined location.
Swagger is configured to endpoint/swagger
and Swagger UI opens when project is started from IDE.
Caching can be disabled fromappsettings.json
by setting ETag.Enabled tofalse
.
"Caching": {"ETag": {"Enabled":true }}
If caching is enabled,ETag is added to response headers.
$ curl -v'http://localhost:57602/api/users?age=40'
200 OKHeaders:ETag: "5yZCXmjhk5ozJyTK4-OJkkd_X18"
If a request contains theIf-None-Match
header, the header's value is compared to the response's body and if the value matches to the body's checksum then304 Not Modified
is returned.
$ curl -H"If-None-Match:\"5yZCXmjhk5ozJyTK4-OJkkd_X18\""'http://localhost:57602/api/users?age=40'
If thePUT
request contains theIf-Match
header, the header's value is compared to the item to be updated. If the value matches to the item's checksum then items is updated, else412 Precondition Failed
is returned.
Client can determine what type of representation is desired withAccept
header. By default data is returned in JSON (text/json
,application/json
).
Supported types areJSON,CSV andXML.
text/jsonapplication/jsontext/csvtext/xmlapplication/xml
Get all users inCSV
$ curl -H"Accept: text/csv" http://localhost:57603/api/users
If content types is not supported406 Not Acceptable
is returned.
Delay and errors can be configured fromappsettings.json
.
Delay can be simulated by settingSimulate.Delay.Enabled
totrue. The inbound request is delayed. The length of the delay is randomly chosen betweenMinMs
andMaxMs
. Delay can be configured for only certain HTTP Methods, e.g. only POST updates have delay and all GET requests are handled normally.
"Simulate": {"Delay": {"Enabled":true,"Methods": ["GET","POST","PUT","PATCH","DELETE" ],"MinMs":2000,"MaxMs":5000 }}
Random errors can be simulated by settingSimulate.Error.Enabled
totrue. Error is thrown if setProbability
is greater or equal to randomly chosen value between 1 and 100. Error can be configured for only certain HTTP Methods.
"Simulate": {"Error": {"Enabled":true,"Methods": ["POST","PUT","PATCH","DELETE" ],"Probability":50 }}
Error simulation is always skipped for Swagger, WebSocket (ws) and for any html file.
Fake Server has a custom response middleware to transform reponse body with C#-scripts.
Multiple scripts can be configured and if path matches multiple scipts, last match will be used.
"CustomResponse": {"Enabled":true,"Scripts": [ {"Script":"return new { Data = _Body, Success = _Context.Response.StatusCode == 200 };","Methods": ["GET" ],"Paths": ["api" ],"Usings": ["System","Microsoft.AspNetCore.Http" ],"References": ["Microsoft.AspNetCore" ] }, {"Script":"return new { Data =\"illegal operation\" };","Methods": ["GET" ],"Paths": ["api/users" ],"Usings": ["System","Microsoft.AspNetCore.Http" ],"References": ["Microsoft.AspNetCore" ] } ]}
C# code is executed as a csscript and it has some special reacy processed objects.
// HttpContextpublicHttpContext_Context;// Collection id parsed from the Request pathpublicstring_CollectionId;// Original Response Body encoded to stringpublicstring_Body;// Request Http Methodpublicstring_Method;
Example script creates new anonymous object
return new { Data = _Body, Success = _Context.Response.StatusCode == 200 };
Previous script will have a response body:
{ "Data": [ { "id": 1, "name": "James" ...}, { "id": 2, "name": "Phil", ... }, ... ], "Success": true}
If response data requires so dynamically named properties, e.g.users
in the example, then response requires more complex processing.
{ "Data": { "users": [ { "id": 1, "name": "James" ...}, { "id": 2, "name": "Phil", ... }, ... ] }, "Success": true}
C#-code for the processing would be following:
vardata=newExpandoObject();vardataItems=dataasIDictionary<string,object>;dataItems.Add(_CollectionId,_Body);varbody=newExpandoObject();varitems=bodyasIDictionary<string,object>;items.Add("Data",data);items.Add("Success",_Context.Response.StatusCode==200);returnbody;
Script also would needSystem.Collections.Generic
andSystem.Dynamic
as imports.
{"Script":"var data = new ExpandoObject();var dataItems = data as IDictionary<string, object>;dataItems.Add(_CollectionId, _Body);var body = new ExpandoObject();var items = body as IDictionary<string, object>;items.Add(\"Data\", data);items.Add(\"Success\", _Context.Response.StatusCode == 200);return body;","Methods": ["GET" ],"Paths": ["api" ],"Usings": ["System","System.Dynamic","System.Collections.Generic","Microsoft.AspNetCore.Http" ],"References": ["Microsoft.AspNetCore" ]}
Fake JSON Server writes a log file to the application base path (execution folder).
Console logging can be enabled fromappsettings.json
by adding a new item toSerilog.WriteTo-array.
"Serilog": {"WriteTo": [ {"Name":"File" }, {"Name":"Console" } ]}
GET /POST /tokenPOST /logoutPOST /admin/reloadGET /healthGET /apiHEAD /apiGET /api/{collection/object}HEAD /api/{collection/object}POST /api/{collection}GET /api/{collection}/{id}HEAD /api/{collection}/{id}PUT /api/{collection}/{id}PATCH /api/{collection}/{id}DELETE /api/{collection}/{id}PUT /api/{object}PATCH /api/{object}DELETE /api/{object}OPTIONS /api/*GET /async/queue/{id}DELETE /async/queue/{id}POST /async/{collection}PUT /async/{collection}/{id}PATCH /async/{collection}/{id}DELETE /async/{collection}/{id}OPTIONS /async/*POST /graphql
Fake JSON Server is designed for prototyping, so by default it supports only resources in a collection.
If the JSON-file has a single object on a root level, then the route from that property is handled like a single object.
{"collection": [],"object": {}}
Dynamic routes are defined by the name of item's collection and id:api/{collection}/{id}
. All examples below useusers
as a collection name.
If/api
or/async
are needed to change to something different, changeApiRoute
orAsyncRoute
fromConfig.cs
.
publicclassConfig{publicconststringApiRoute="api";publicconststringAsyncRoute="async";publicconststringGraphQLRoute="graphql";publicconststringTokenRoute="token";publicconststringTokenLogoutRoute="logout";}
For example, ifapi
-prefix is not wanted in the route, then removeapi
fromApiRoute
.
publicconststringApiRoute="";
# Query with default route$ curl'http://localhost:57602/api/users?skip=5&take=20'# Query with updated route$ curl'http://localhost:57602/users?skip=5&take=20'
id
is used as the identifier field. By default Id field's type isinteger.POST
will always use integer as id field's type.
"users":[ {"id":1 }],"sensors": [ {"id":"E:52:F7:B3:65:CC" }]
Ifstring is used as the identifiers type, then items must be inserted withPUT
andUpsertOnPut
must be set totrue fromappsettings.json
.
Method return codes are specified inREST API Tutorial.
Asynchoronous operations follow theREST CookBook guide. Updates will return202
with location header to queue item. Queue will return200
while operation is processing and303
when job is ready with location header to changed or new item.
Name of the Id-field used by Data Store can be configure fromappsettings.json
. Default name for the id-field isid
.
"DataStore": {"IdField":"id"}
By default Data Store updates its internal data on every request by reading the data from the JSON file.
EagerDataReload
can be configured fromappsettings.json
.
"DataStore": {"EagerDataReload":true}
For performance reasonsEagerDataReload
can be changed tofalse. Then the data is reloaded from the file only when Data Store is initialized and when the data is updated.
IfEagerDataReload
isfalse and JSON file is updated manually, reload endpoint must be called if new data will be queried before any updates.
Reload endpoint can be used to reload JSON data from the file to Data Store. Endpoint is in Admin controller, so it is usable also with Swagger.
$ curl -X POST http://localhost:57602/admin/reload --data""
The health check endpoint provides status information about the Fake JSON Server. It monitors critical dependencies (like the data store) and reports service status, uptime, and version information.
> GET /health200 OK : Application is healthy503 Service Unavailable : Application is unhealthy (data store is inaccessible)
The response contains:
status
: "Healthy" when all services are operational, "Unhealthy" otherwiseuptime
: Duration since application startup in days, hours, and minutes (only when healthy)version
: Application version number
Example of a healthy response:
$ curl http://localhost:57602/health
{"status":"Healthy","uptime":"2 days, 5 hours, 30 minutes","version":"1.0.0"}
Example of an unhealthy response:
{"status":"Unhealthy","version":"1.0.0"}
This endpoint is useful for:
- Monitoring service health in production environments
- Integration with container orchestration systems for health probes
- Checking if the data store is accessible
Data used in example requests, unless otherwise stated:
{"users": [ {"id":1,"name":"Phil","age":40,"location":"NY" }, {"id":2,"name":"Larry","age":37,"location":"London" }, {"id":3,"name":"Thomas","age":40,"location":"London" } ],"movies": [],"configuration": {"ip":"192.168.0.1" }}
Example JSON generation guide for data used in unit testsCreateJSON.md.
> GET /api200 OK : List of collections
Get all collections.
$ curl http://localhost:57602/api
["users","movies","configuration" ]
> GET /api/{collection}200 OK : Collection is found400 Bad Request : Invalid query parameters404 Not Found : Collection is not found
By default the request returns results in an array. Headers have the collection's total item count (X-Total-Count
) and pagination links (Link
).
$ curl http://localhost:57602/api/users
[ { "id": 1, "name": "Phil", "age": 40, "location": "NY" }, { "id": 2, "name": "Larry", "age": 37, "location": "London" }, { "id": 3, "name": "Thomas", "age": 40, "location": "London" }, ...]Headers:X-Total-Count=20Link=<http://localhost:57602/api/users?offset=15&limit=5>; rel="next",<http://localhost:57602/api/users?offset=15&limit=5>; rel="last",<http://localhost:57602/api/users?offset=0&limit=5>; rel="first",<http://localhost:57602/api/users?offset=5&limit=5>; rel="prev"
The return value can also be a JSON object. SetUseResultObject
totrue fromappsettings.json
.
"Api": {"UseResultObject":true}
JSON object has items in results array in result field, link object has the pagination info, skip, take and total count fields.
{"results": [],"link": {"Prev":"http://localhost:57602/api/users?offset=5&limit=5","Next":"http://localhost:57602/api/users?offset=15&limit=5","First":"http://localhost:57602/api/users?offset=0&limit=5","Last":"http://localhost:57602/api/users?offset=15&limit=5" },"offset":10,"limit":5,"count":20}
Single object doesn't support result object. If the endpoint is a single object, only item object is returned.
$ curl http://localhost:57602/api/configuration
{"ip":"192.168.0.1" }
Slicing can be defined withskip
/take
,offset
/limit
orpage
/per_page
parameters. By default request returns the first 512 items.
Example request returns items from 11 to 20.
# skip and take$ curl'http://localhost:57602/api/users?skip=10&take=10'# offset and limit$ curl'http://localhost:57602/api/users?offset=10&limit=10'# page and per_page$ curl'http://localhost:57602/api/users?page=2&per_page=10'
Link items are optional, so e.g. if requested items are starting from index 0, then the prev and first page link won't be added to the Link header.
Headers followGitHub Developer guide.
> GET api/{collection}?sort=[+/-]field,[+/-]otherField
Sort contains comma-spearetd list of fields defining the sort. Sort direction can be specified with+
(ascending) or-
(descending, default) prefix.
Get all users sorted bylocation
(descending) and then byage
(ascending).
$ curl'http://localhost:57602/api/users?sort=location,+age'
[ {"id":2,"name":"Larry","age":37,"location":"London" }, {"id":3,"name":"Thomas","age":40,"location":"London" }, {"id":1,"name":"Phil","age":40,"location":"NY" }]
> GET api/{collection}?field=value&otherField=value
Get all users whoseage
equals to40.
$ curl'http://localhost:57602/api/users?age=40'
[ {"id":1,"name":"Phil","age":40,"location":"NY" }, {"id":3,"name":"Thomas","age":40,"location":"London" }]
Query filter can include operators. Operator identifier is added to the end of the field.
> GET api/{collection}?field{operator}=value= : Equal to_ne= : Not equal_lt= : Less than_gt= : Greater than_lte= : Less than or equal to_gte= : Greater than or equal to
Query users withage
less than40.
$ curl http://localhost:57602/api/users?age_lt=40
[ {"id":2,"name":"Larry","age":37,"location":"London" }]
Query can have a path to child properties. Property names are separated by periods.
> GET api/{collection}?parent.child.grandchild.field=value
Example JSON:
[ {"companyName":"ACME","employees": [ {"id":1,"name":"Thomas","address": {"city":"London" } } ] }, {"companyName":"Box Company","employees": [ {"id":1,"name":"Phil","address": {"city":"NY" } } ] }]
Get all companies which has employees withLondon inaddress.city
.
$ curl http://localhost:57602/api/companies?employees.address.city=London
Query will return ACME from the example JSON.
[ {"companyName":"ACME","employees": [ {"id":1,"name":"Thomas","address": {"city":"London" } } ] }]
Full-text search can be performed with theq
-parameter followed by search text. Search is not case sensitive.
> GET api/{collection}?q={text}
Get all users that contain textLondon in the value of any of it's properties.
$ curl http://localhost:57602/api/users?q=london
Choose which fields to include in the results. Field names are separated by comma.
> GET api/{collection}?fields={fields}
Selectage
andname
from users.
$ curl http://localhost:57602/api/users?fields=age,name
[ {"name":"Phil","age":40 }, {"name":"Larry","age":37 }]
> GET /api/{collection}/{id}200 OK : Item is found400 Bad Request : Collection is not found404 Not Found : Item is not found
Get user withid
1.
$ curl http://localhost:57602/api/users/1
{"id":1,"name":"Phil","age":40,"location":"NY" }
> GET /api/{collection}/{id}/{restOfThePath}200 OK : Nested item is found400 Bad Request : Parent item is not found404 Not Found : Nested item is not found
It is possible to request only child objects instead of full item. Path to nested item can contain id field integers and property names.
[ {"id":0,"companyName":"ACME","employees": [ {"id":1,"name":"Thomas","address": {"city":"London" } } ] }]
Example query will return address object from the employee withid
1 from the company withid
0.
$ curl http://localhost:57602/api/company/0/employees/1/address
{"address": {"city":"London" } }
> POST /api/{collection}201 Created : New item is created400 Bad Request : New item is null409 Conflict : Collection is an object
Add{ "name": "Phil", "age": 40, "location": "NY" } to users.
$ curl -H"Accept: application/json" -H"Content-type: application/json" -X POST -d'{ "name": "Phil", "age": 40, "location": "NY" }' http://localhost:57602/api/users/
Response has new item's id and a Location header that contains the path to the new item.
{ "id": 6 }Headers:Location=http://localhost:57602/api/users/6
If collection is empty and new item has anid-field set, it will be used a firstid-value. Ifid-field is not set,id-value will start from0
.
> PUT /api/{collection}/{id}204 No Content : Item is replaced400 Bad Request : Item is null404 Not Found : Item is not found
Replace user withid
1 with object{ "name": "Roger", "age": 28, "location": "SF" }.
$ curl -H"Accept: application/json" -H"Content-type: application/json" -X PUT -d'{ "name": "Roger", "age": 28, "location": "SF" }' http://localhost:57602/api/users/1
Server supportsJSON patch andJSON merge patch.
> PATCH /api/{collection}/{id}Content-type: application/json-patch+json204 No Content : Item updated400 Bad Request : PATCH is empty404 Not Found : Item is not found415 Unsupported Media Type : Content type is not supported
Setage
to41 andwork.rating
to3.2 from user withid
1.
$ curl -H"Accept: application/json" -H"Content-type: application/json-patch+json" -X PATCH -d'[{ "op": "replace", "path": "age", "value": 41}, { "op": "replace", "path": "work/rating", "value": 3.2 }]' http://localhost:57602/api/users/1
[ {"op":"replace","path":"age","value":41}, {"op":"replace","path":"work/rating","value":3.2 }]
> PATCH /api/{collection}/{id}Content-type: application/json+merge-patch or application/merge-patch+json204 No Content : Item updated400 Bad Request : PATCH is empty404 Not Found : Item is not found415 Unsupported Media Type : Content type is not supported
Setage
to41 andwork.rating
to3.2 from user withid
1.
$ curl -H"Accept: application/json" -H"Content-type: application/json+merge-patch" -X PATCH -d'{ "age": "41", "work": { "rating": 3.2 }}' http://localhost:57602/api/users/1
{"age":41,"work": {"rating":3.2 }}
NOTE:
Due to the limitations of the merge patch, if the patch is anything other than an object, the result will always be to replace the entire target with the entire patch. Also, it is not possible to patch part of a target that is not an object, such as to replace just some of the values in an array.
https://tools.ietf.org/html/rfc7396#section-2
> DELETE /api/{collection}/{id}204 No Content : Item deleted404 Not Found : Item is not found
Delete user with id1.
$ curl -X DELETE http://localhost:57602/api/users/1
OPTIONS method will returnAllow
header with a list of HTTP methods that may be used on the resource.
$ curl -X OPTIONS -v http://localhost:57602/api/
200 OKHeaders:Allow: GET, POST, OPTIONS
HEAD method can be used to get the metadata and headers without receiving response body.
E.g. get user count without downloading large response body.
$ curl -X HEAD -v http://localhost:57602/api/users
200 OKHeaders:X-Total-Count: 1249
/async
endpoint has long running operation for each update operation.
> POST/PUT/PATCH/DELETE /async/{collection}/{id}202 Accepted : New job started400 Bad Request : Job not startedHeaders:Location=http://{url}:{port}/async/queue/{id}
Update operations will return location to job queue in headers.
Create new item. Curl has a verbose flag (-v
). When it is used, curl will print response headers among other information.
$ curl -H"Accept: application/json" -H"Content-type: application/json" -X POST -d'{ "name": "Phil", "age": 40, "location": "NY" }' -v http://localhost:57602/async/users/
> GET /async/queue/{id}200 OK : Job running303 See Other : Job ready404 Not Found : Job not foundHeaders:Location=http://{url}:{port}/api/{collectionId}/{id}
When Job is ready, status code will beredirect See Other. Location header will have modified item's url.
After job is finished, it must be deleted manually
> DELETE /async/queue/{id}204 No Content : Job deleted404 Not Found : Job not found
Delay for operations can be set fromappsettings.json
. With long delay it is easier to simulate long running jobs.
"Jobs": {"DelayMs":2000 }
Delay value is milliseconds. Default value is 2000ms.
GraphQL implementation is experimental and supports only basic queries and mutations. At the moment this is a good way to compare simple GraphQL and REST queries./graphql
endpoint accepts requests withapplication/graphql
orapplication/json
content type. If the first, request body is GraphQL query string, whereas if the latter, request body is expected to be a valid JSON with parameterquery
containing the GraphQL query string.
> POST /graphqlContent-type: application/graphqlBody: [query/mutation]ORContent-type: application/jsonBody: { "query": "[query/mutation]" }200 OK : Query/mutation successful 400 Bad Request : Query/mutation contains errors501 Not Implemented : HTTP method and/or content-type combination not implemented
Alternatively, the/graphql
endpoint also supports requests containing a valid GraphQL query as aquery
query parameter using either a GET or POST request. Queries in the JSON format are not supported as query parameters. Note that in the case of a POST request, the query supplied using the query parameter will take priority over any content in the request body, which will be ignored if thequery
query parameter is present.
> GET /graphql?query=[query/mutation]OR> POST /graphql?query=[query/mutation]200 OK : Query/mutation successful 400 Bad Request : Query/mutation contains errors501 Not Implemented : HTTP method and/or content-type combination not implemented
Response is in JSON format. It containsdata
anderrors
fields.errors
field is not present if there are no errors.
{ "data": { "users": [ ... ], ... }, "errors": [ ... ]}
Implementation usesgraphql-dotnet to parse Abstract Syntax Tree from the query.
Query implementation supports equal filtering with arguments. Query's first field is the name of the collection.
query { [collection](filter: value) { [field1] [field2](filter: value) { [field2.1] } [field3] }}
Implementation accepts queries with operation type, with any query name (which is ignored) and query shorthands.
# Operation typequery {users(id:3) {namework {location } }}# Optional query namequerygetUsers {users {namework {location } }}# Query shorthand{families {familyNamechildren(age:5){name } }}
Example: getfamilyName
andage
of thechildren
fromfamilies
whereid
is 1 andname
from allusers
.
{families(id:1) {familyNamechildren {age } }users {name }}
Execute query with curl:
$ curl -H"Content-type: application/graphql" -X POST -d"{ families(id: 1) { familyName children { age } } users { name } }" http://localhost:57602/graphql
Respose:
{"data": {"families": [ {"familyName":"Day","children": [ {"age":14 }, {"age":18 }, {"age":9 } ] } ],"users": [ {"name":"James" }, {"name":"Phil" }, {"name":"Raymond" }, {"name":"Jarvis" } ] }}
Fake JSON Server supports dynamic mutations with the format defined below:
mutation { [mutationName](input: { [optional id] [itemData/patch] }) { [collection]{ [fields] }}
Action is decided from the mutation name. Name follows patternadd|update|replace|delete[collection] E.g.deleteUsers will delete an item from theusers collection. Input object has an optional id-field and update data object. Return data is defined the same way as in queries.
add{collection}
Input contains object to be added with the collection's name.
mutation {addUsers(input: {users: {name: Jameswork: {name: ACME } } }) {users {idname } }}
Execute mutation with curl:
$ curl -H"Content-type: application/graphql" -X POST -d"mutation { addUsers(input: { users: { name: James work: { name: ACME } } }) { users { id name } } }" http://localhost:57602/graphql
Response:
{"data": {"users":{"id":12,"name":"James" } }}
update{collection}
mutation {updateUsers(input: {id:2patch:{name: Timothy } }) {users {idname } }}
Execute mutation with curl:
$ curl -H"Content-type: application/graphql" -X POST -d"mutation { updateUsers(input: { id: 2 patch:{ name: Timothy } }) { users { id name age }}}" http://localhost:57602/graphql
Response:
{"data": {"users": {"id":2,"name":"Timothy","age":25 } } }
NOTE: Update doesn't support updating child arrays
replace{collection}
Input must contain id of the item to be replacecd and items full data in object named with collection's name.
mutation {replaceUsers(input: {id:5users:{name: Rickage:44workplace: {companyName: ACME } } }) {users {idnameage } }}
Execute mutation with curl:
$ curl -H"Content-type: application/graphql" -X POST -d"mutation { replaceUsers(input: { id: 1 users: { name: Rick age: 44 workplace: { name: ACME } } }) {users {id name age}}}" http://localhost:57602/graphql
Response:
{"data": {"users": {"id":1,"name":"Rick","age":44 } }}
delete{collection}
Delete requires only the id of item to be deleted. Response will only contain success booleantrue/false
, so mutation doesn't need any definition for return data.
mutation {deleteUsers(input: {id:4 })}
Execute mutation with curl:
$ curl -H"Content-type: application/graphql" -X POST -d"mutation { deleteUsers(input: { id: 4 }) }" http://localhost:57602/graphql
Response:
{"data": {"Result":true }}
API follows best practices and recommendations from these guides:
- REST CookBook
- REST API Tutorial
- Zalando Restful API Guidelines
- Microsoft API Design
- GitHub v3 Guide
- Introduction to GraphQL
- MDN Web Docs: ETag
- Designing GraphQL Mutations
- IETF Tools
Releases are marked with Tag and can be found fromReleases.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Licensed under theMIT License.
About
Fake JSON Server is a Fake REST API that can be used as a Back End for prototyping or as a template for a CRUD Back End.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.