Designing a REST API I'd like to implement the following structure with a clear distinction between the returned object(s) and any relevant metadata
{
"data": [
{
"id": 1,
"clockingTime": "2022-08-10T15:32+02:00[Europe/Paris]",
"comment": 101,
"crudType": 1
}
],
"meta": {
"creationTime": "2022-08-11T17:10:40.045+0200",
"correlationId": "93b058ad-5383-4054-b284-342d3041f79f"
}
}
This is achieved by having a top level object RestResponseObject containing data and meta with the data object being extended by all objects-to-return
#GetMapping(value = "/test")
public ResponseEntity<RestResponseObject> test() {
RestResponseObject restResponseObject = new RestResponseObject();
restResponseObject.setData(new FooDTO());
restResponseObject.setMeta(new RestMetaObject());
return new ResponseEntity<>(restResponseObject , HttpStatus.OK);
}
the issue is that this obfuscates the actual object being returned and swagger will not show the scheme with relevant variables and/or types
Is this the wrong way to implement a data/meta object structure or is there no other way to show the actual objects being returned
Related
Given the following JSON example:
{
"root": {
"child-1": {
"grandchild-1": "value1",
"grandchild-2": "value2",
"grandchild-3": "value3"
},
"child-2": {
"grandchild-4": "value4",
"grandchild-5": {
"grandgrandchild-1": "value5"
}
}
}
}
How to build a PostgreSQL query, using (one single) json-path that would return multiple object values?
E.g., [value3, value5]
The closest I came to is the following query:
select jsonb_path_query(resp_json, '$.*.child-1.grandchild-3'),
jsonb_path_query(resp_json, '$.*.child-2.grandchild-5.grandgrandchild-1')
from req_resp_body;
The obvious issue with this approach is that it requires one jsonb_path_query function call for each object. Given that the incoming nr. of objects is indefinite, this is unusable.
Notes:
The '*' instead of 'root' is on purpose, since the user of the query might not know the actual root name
I am working with a given JSON response. The API I'm using provides responses like such:
{
"data":[
{
"sample-value": "sample"
}
{
"sample-value": "sample"
}
{
"sample-value": "sample"
}
{
"sample-value": "sample"
}
],
"meta": {
"current-page": 1,
"next-page": 2,
"prev-page": null,
"total-pages": 5,
"total-count": 4338,
"filters": {}
},
"links": {
"self": "linktothisquery",
"next": "linktonextquery",
"last": "linktolastpagequery"
}
}
As you can see, the response provided contains what I interpret to be 1 object array (size changes depending on what is being queried) and 2 objects. (data is the array, meta and links are the objects) I have ran into a situation where I need to run multiple requests in order to get the full amount of data required for my project. I'm attempting to get around this by iterating through requests, but due to the variance in response length per-request I cannot use the same logic to locate only the array in the response and thus end up with unexpected characters making GSON unable to parse. I'm currently doing this by using String.substring() and manually inputting the location inside of the response that I want GSON to parse. Basically, I want GSON to ONLY see the "data" array and ignore everything else. I have model classes in my project to serialize the data, but they are built around the objects inside of the afforementioned array and not the array itself.
Your posted JSON is invalid .In data array comma is missing in between two objects. It should be
{
"sample-value": "sample"
},
{
"sample-value": "sample"
}
Now if you just want the data array part you can manually parse it using JsonParser. It will be the easiest way to do it.
String json = "{\"data\":[{\"sample-value\":\"sample\"},{\"sample-value\":\"sample\"},{\"sample-value\":\"sample\"},{\"sample-value\":\"sample\"}],\"meta\":{\"current-page\":1,\"next-page\":2,\"prev-page\":null,\"total-pages\":5,\"total-count\":4338,\"filters\":{}},\"links\":{\"self\":\"linktothisquery\",\"next\":\"linktonextquery\",\"last\":\"linktolastpagequery\"}}";
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
JsonArray jsonArray = jsonObject.get("data").getAsJsonArray();
jsonArray.forEach(System.out::println);
Output:
{"sample-value":"sample"}
{"sample-value":"sample"}
{"sample-value":"sample"}
{"sample-value":"sample"}
We have a relatively big json document but just need to the special fields of it. So, I defined the needed properties in my model and can serialize/deserialize, well. Recently we are forced to hand over the json document as we received, but since there are so much fields and these fields vary frequently, I'm looking for a method to do this without defining extra fields in the model. I couldn't do it by using an extra Map<String, Object> in the model classes but I guess there should be an solution for it.
Let's suppose my model is like this:
public class Model {
public A a;
}
public class A {
public int i;
}
and the json is like this:
{
"a": {
"i": "1",
"j": {
"q": 2.11,
"e": "94300000",
"r": "book",
"t": null
},
"b": 1
},
"ff": [
{
"gg": "ttttttttt",
"dd": "oooooooo",
"jj": null,
"kk": [
"pppppppp"
]
},
{
"mm": null
}
]
}
How can I do it?
Updated:
Please, take a look at following.
For this example, it has two pretty the same objects inside. With two fields for each of them - id and is_deleted.
{
"meta": {
"delete_count": 1,
"status": [
{
"id": 1,
"is_deleted": true
},
{
"id": 2,
"is_deleted": false
}
]
}
}
Let's imagine 2 different occasions:
every id has changed to uid
status has changed to stat, the only is_deleted field has changed to just deleted(if this is possible. let's imagine it is)
So, I have a schema for this payload. But, it checks for field types not for field names.
it uses com.jayway.restassured.module.jsv
JsonObject has a method which returns true if key exist public boolean has(java.lang.String key)
JSONObject jsonObj = new JSONObject(Your_STRING);
if (jsonObj.has("org_id")) {
//Do stuff
}
for more details you can check below -
check key exist
try to verify if org_id exists, the question isn't clear!.
I am trying to set up a RESTful API with Spring, using react for the front-end. The client is meant to send a POST request that looks something like this:
{
"previousDecisions": [0, 1, 2]
}
Then the server will respond with an Object called Node which looks like this after being converted to JSON:
{
"id": 0,
"text": "Something here...",
"decisions": [],
"children": [],
"speaker": 0,
"checkpoint": true
}
I am struggling to follow some of the example code I have seen for how to set this up using Spring.
The way the back end is set up is:
There is a Decide class, a Node class, and a DecideController class. DecideController is supposed to take a POST request like above and then use the Decide class to get an instance of the Node class and use it as a response to the client.
I haven't begun testing the client side of things yet, but I am using Intellij Restful API tool to check if its working and it is giving me an error. Heres what I have for the actual method which should be handling the POST Request:
#RestController
public class DecideController {
#PostMapping("/decide")
public Node decide(#Valid #RequestBody Decide decide) {
return decide.getNode();
}
}
I am getting an error response when I send a request with this body:
{
"previousDecisions": [0, 1, 2]
}
And with these headers:
Accept: application/json
Cache-Control: no-cache
This is the error response:
{"timestamp":"2019-09-01T23:54:58.037+0000","status":500,"error":"Internal Server Error","message":"Content-Type cannot contain wildcard type '*'","path":"/decide"}
The last thing I can think of that you might need to help me out is the Decide class and it is pretty short so I will include that here as well:
public class Decide {
private int[] decisionList;
public Decide(int[] decisionList) {
this.decisionList = decisionList;
}
public Node getNode() {
//Use the game class to get a root node for the entire story tree
Node rootNode = (new Game()).getFullStoryTree();
//Traverse the story tree using the decisionList to get to the current node
Node currentNode = rootNode;
for (int whichChild : this.decisionList) {
currentNode = currentNode.getChild(whichChild);
}
return currentNode;
}
}
As said about what I am expecting from that POST request is a response that looks like this:
{
"id": 0,
"text": "Something here...",
"decisions": [],
"children": [],
"speaker": 0,
"checkpoint": true
}
Sorry I am pretty new to all of this so hopefully everything I said here makes sense, but if not I am happy to clarify or provide more information. Thank you!!
The error is coming from the server, because of the client:
"Internal Server Error","message":"Content-Type cannot contain wildcard type '*'"
Even though the PAYLOAD looks ok, your react client is setting the Content-Type HTTP header to "*". You need to fix the problem in react.
SUGGESTION:
Follow this link to set Content-Type to application/json.