programing

표준 JSON API 응답 형식?

nasanasas 2020. 10. 2. 22:31
반응형

표준 JSON API 응답 형식?


API에서 JSON 응답을 구조화하기위한 표준 또는 모범 사례가 있습니까? 분명히 모든 응용 프로그램의 데이터는 다르기 때문에 내가 신경 쓰지 않는 것이 아니라 "응답 상용구"입니다. 내가 의미하는 바의 예 :

성공적인 요청 :

{
  "success": true,
  "payload": {
    /* Application-specific data would go here. */
  }
}

실패한 요청 :

{
  "success": false,
  "payload": {
    /* Application-specific data would go here. */
  },
  "error": {
    "code": 123,
    "message": "An error occurred!"
  }
}

예, 몇 가지 표준 (표준 정의에 대한 일부 자유이긴하지만)이 등장했습니다.

  1. JSON API -JSON API는 응답뿐만 아니라 리소스 생성 및 업데이트도 다룹니다.
  2. JSend- 단순하고 아마도 이미하고있는 일입니다.
  3. OData JSON 프로토콜 -매우 복잡합니다.
  4. HAL -OData와 비슷하지만 HATEOAS 와 같은 것을 목표로합니다 .

JSON API 설명 형식도 있습니다.

  • 멋진
    • JSON 스키마 (Swagger에서 사용하지만 독립적으로 사용할 수 있음)
  • JSON의 WADL
  • RAML
  • HAL 은 이론상 HATEOAS 가 자기 설명 이기 때문 입니다.

Google JSON 가이드

성공 응답 반환 data

{
  "data": {
    "id": 1001,
    "name": "Wing"
  }
}

오류 응답 반환 error

{
  "error": {
    "code": 404,
    "message": "ID not found"
  }
}

클라이언트가 JS 인 if ("error" in response) {}경우 오류가 있는지 확인 하는 사용할 수 있습니다 .


나는 사실상의 표준이 실제로 등장하지 않았을 것이라고 생각합니다. 그러나 상관없이 여기에 내 의견이 있습니다.

성공적인 요청 :

{
  "status": "success",
  "data": {
    /* Application-specific data would go here. */
  },
  "message": null /* Or optional success message */
}

실패한 요청 :

{
  "status": "error",
  "data": null, /* or optional error payload */
  "message": "Error xyz has occurred"
}

장점 : 성공 및 오류 사례 모두에서 동일한 최상위 요소

단점 : 오류 코드는 없지만 원하는 경우 상태를 (성공 또는 실패) 코드로 변경하거나 "code"라는 다른 최상위 항목을 추가 할 수 있습니다.


질문이 REST 웹 서비스 디자인에 관한 것이고 더 정확하게는 성공 / 오류에 관한 것이라고 가정합니다.

디자인에는 3 가지 종류가 있다고 생각합니다.

  1. Use only HTTP Status code to indicate if there was an error and try to limit yourself to the standard ones (usually it should suffice).

    • Pros: It is a standard independent of your api.
    • Cons: Less information on what really happened.
  2. Use HTTP Status + json body (even if it is an error). Define a uniform structure for errors (ex: code, message, reason, type, etc) and use it for errors, if it is a success then just return the expected json response.

    • Pros: Still standard as you use the existing HTTP status codes and you return a json describing the error (you provide more information on what happened).
    • Cons: The output json will vary depending if it is a error or success.
  3. Forget the http status (ex: always status 200), always use json and add at the root of the response a boolean responseValid and a error object (code,message,etc) that will be populated if it is an error otherwise the other fields (success) are populated.

    • Pros: The client deals only with the body of the response that is a json string and ignores the status(?).

    • Cons: The less standard.

It's up to you to choose :)

Depending on the API I would choose 2 or 3 (I prefer 2 for json rest apis). Another thing I have experienced in designing REST Api is the importance of documentation for each resource (url): the parameters, the body, the response, the headers etc + examples.

I would also recommend you to use jersey (jax-rs implementation) + genson (java/json databinding library). You only have to drop genson + jersey in your classpath and json is automatically supported.

EDIT:

  • Solution 2 is the hardest to implement but the advantage is that you can nicely handle exceptions and not only business errors, initial effort is more important but you win on the long term.

  • Solution 3 is the easy to implement on both, server side and client but it's not so nice as you will have to encapsulate the objects you want to return in a response object containing also the responseValid + error.


I will not be as arrogant to claim that this is a standard so I will use the "I prefer" form.

I prefer terse response (when requesting a list of /articles I want a JSON array of articles).

In my designs I use HTTP for status report, a 200 returns just the payload.

400 returns a message of what was wrong with request:

{"message" : "Missing parameter: 'param'"}

Return 404 if the model/controler/URI doesn't exist

If there was error with processing on my side, I return 501 with a message:

{"message" : "Could not connect to data store."}

From what I've seen quite a few REST-ish frameworks tend to be along these lines.

Rationale:

JSON is supposed to be a payload format, it's not a session protocol. The whole idea of verbose session-ish payloads comes from the XML/SOAP world and various misguided choices that created those bloated designs. After we realized all of it was a massive headache, the whole point of REST/JSON was to KISS it, and adhere to HTTP. I don't think that there is anything remotely standard in either JSend and especially not with the more verbose among them. XHR will react to HTTP response, if you use jQuery for your AJAX (like most do) you can use try/catch and done()/fail() callbacks to capture errors. I can't see how encapsulating status reports in JSON is any more useful than that.


Following is the json format instagram is using

{
    "meta": {
         "error_type": "OAuthException",
         "code": 400,
         "error_message": "..."
    }
    "data": {
         ...
    },
    "pagination": {
         "next_url": "...",
         "next_max_id": "13872296"
    }
}

The RFC 7807: Problem Details for HTTP APIs is at the moment the closest thing we have to an official standard.


For what it's worth I do this differently. A successful call just has the JSON objects. I don't need a higher level JSON object that contains a success field indicating true and a payload field that has the JSON object. I just return the appropriate JSON object with a 200 or whatever is appropriate in the 200 range for the HTTP status in the header.

However, if there is an error (something in the 400 family) I return a well-formed JSON error object. For example, if the client is POSTing a User with an email address and phone number and one of these is malformed (i.e. I cannot insert it into my underlying database) I will return something like this:

{
  "description" : "Validation Failed"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Invalid phone number."
  } ],
}

Important bits here are that the "field" property must match the JSON field exactly that could not be validated. This allows clients to know exactly what went wrong with their request. Also, "message" is in the locale of the request. If both the "emailAddress" and "phoneNumber" were invalid then the "errors" array would contain entries for both. A 409 (Conflict) JSON response body might look like this:

{
  "description" : "Already Exists"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Phone number already exists for another user."
  } ],
}

With the HTTP status code and this JSON the client has all they need to respond to errors in a deterministic way and it does not create a new error standard that tries to complete replace HTTP status codes. Note, these only happen for the range of 400 errors. For anything in the 200 range I can just return whatever is appropriate. For me it is often a HAL-like JSON object but that doesn't really matter here.

The one thing I thought about adding was a numeric error code either in the the "errors" array entries or the root of the JSON object itself. But so far we haven't needed it.


Their is no agreement on the rest api response formats of big software giants - Google, Facebook, Twitter, Amazon and others, though many links have been provided in the answers above, where some people have tried to standardize the response format.

As needs of the API's can differ it is very difficult to get everyone on board and agree to some format. If you have millions of users using your API, why would you change your response format?

Following is my take on the response format inspired by Google, Twitter, Amazon and some posts on internet:

https://github.com/adnan-kamili/rest-api-response-format

Swagger file:

https://github.com/adnan-kamili/swagger-sample-template


The point of JSON is that it is completely dynamic and flexible. Bend it to whatever whim you would like, because it's just a set of serialized JavaScript objects and arrays, rooted in a single node.

What the type of the rootnode is is up to you, what it contains is up to you, whether you send metadata along with the response is up to you, whether you set the mime-type to application/json or leave it as text/plain is up to you (as long as you know how to handle the edge cases).

Build a lightweight schema that you like.
Personally, I've found that analytics-tracking and mp3/ogg serving and image-gallery serving and text-messaging and network-packets for online gaming, and blog-posts and blog-comments all have very different requirements in terms of what is sent and what is received and how they should be consumed.

So the last thing I'd want, when doing all of that, is to try to make each one conform to the same boilerplate standard, which is based on XML2.0 or somesuch.

That said, there's a lot to be said for using schemas which make sense to you and are well thought out.
Just read some API responses, note what you like, criticize what you don't, write those criticisms down and understand why they rub you the wrong way, and then think about how to apply what you learned to what you need.


JSON-RPC 2.0 defines a standard request and response format, and is a breath of fresh air after working with REST APIs.


Best Response for web apis that can easily understand by mobile developers.

This is for "Success" Response

{  
   "ReturnCode":"1",
   "ReturnMsg":"Successfull Transaction",
   "ReturnValue":"",
   "Data":{  
      "EmployeeName":"Admin",
      "EmployeeID":1
   }
}

This is for "Error" Response

{
    "ReturnCode": "4",
    "ReturnMsg": "Invalid Username and Password",
    "ReturnValue": "",
    "Data": {}
}

The basic framework suggested looks fine, but the error object as defined is too limited. One often cannot use a single value to express the problem, and instead a chain of problems and causes is needed.

I did a little research and found that the most common format for returning error (exceptions) is a structure of this form:

{
   "success": false,
   "error": {
      "code": "400",
      "message": "main error message here",
      "target": "approx what the error came from",
      "details": [
         {
            "code": "23-098a",
            "message": "Disk drive has frozen up again.  It needs to be replaced",
            "target": "not sure what the target is"
         }
      ],
      "innererror": {
         "trace": [ ... ],
         "context": [ ... ]
      }
   }
}

This is the format proposed by the OASIS data standard OASIS OData and seems to be the most standard option out there, however there does not seem to be high adoption rates of any standard at this point. This format is consistent with the JSON-RPC specification.

You can find the complete open source library that implements this at: Mendocino JSON Utilities. This library supports the JSON Objects as well as the exceptions.

The details are discussed in my blog post on Error Handling in JSON REST API


Concerning your second example, the JSON specification forbids it:

The members data and errors MUST NOT coexist in the same document.

참고URL : https://stackoverflow.com/questions/12806386/standard-json-api-response-format

반응형