I'm trying to add users to a group then return all those users and update their groupid with the group they were just added to. the trouble I'm having is I can't seem the pass the JSON data into my method to alter the groupid field for each user.
I've tried using JSONObject and JSONArray but since I'm not to familiar with it I'm not too sure if I used it right.
#PostMapping(value = "/update")
public List<User> updateGroupID(#RequestBody List<User> incomingusers, Integer groupid) {
List<User> newUserList = new ArrayList<User>();
for(User updateduser : incomingusers){
updateduser.setGroupID(groupid);
userRepo.save(updateduser);
newUserList.add(updateduser);
}
return newUserList;
}
this is the JSON output from the console that is sent to my method. managing multiple users is where I'm having trouble.
data:
0: {username: "seanuser", userTypeID: 2, groupID: null, password: "password", email: "sean#gmail.com", …}
1: {username: "noahuser", userTypeID: 2, groupID: null, password: "password", email: "noah#gmail.com", …}
groupID: 3
this is the code that is supposed to return the users and groupid
saveGroupHandler = () => {
const groupID= this.state.groupId;
const updatedGroup = {...this.state.groupToEdit};
console.log(updatedGroup)
this.setState(state=>({groupSaved:!state.groupSaved}))
axios.post(`http://localhost:8080/user/update/${groupID}`,updatedGroup)
.then(response=>console.log(updatedGroup))
.catch(error =>console.log(error));
}
I'm expecting to get those users into my List of type User so i can then update the groupid.
this is the output I'm getting:
Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
If you have a valid JSON string as mentioned by #Taavi Kivimaa above then you can deserialize it like this:
private ObjectMapper objectMapper = new ObjectMapper();
List<Usere> users = readValue(jsonString, new TypeReference<List<User>>() {});
of course, you'll need to wrap it in a try-catch block.
Related
I am using the openapi-generator to create a spring-boot server. I am currently still in the experimentation phase.
The goal is that the server is able to provide multiple response media-types, depending on the media type that is accepted by the requester. According to different sources, this should be possible. See here for example of how the yaml file would then look. Other similar examples can be found here on stack overflow.
Concrete example. Let's say we have a post request where if a name is posted the name is returned (just a silly example). In case the requester sends the name John Doe and does not accept application/json, the response, in plain text, should look like this:
John Doe
In case the requester accepts application/json the response should look like this:
{"name": "John Doe"}
For explaining my question/problem I created an example spring boot server. At one point it has the path /user for which the response is:
responses:
'200':
description: The username.
content:
application/json:
schema:
properties:
name:
type: string
example: John Doe
text/plain:
schema:
type: string
example: John Doe
On the other hand I created the path /getuser (name is not really fortunate but it is for this example) which returns the following response:
'200':
description: The username.
content:
text/plain:
schema:
type: string
example: John Doe
application/json:
schema:
properties:
name:
type: string
example: John Doe
My problem is the following: for the first example, where I put the application/json first in the yaml file, the API looks like this:
default ResponseEntity<UserPost200Response> userPost(
#Parameter(name = "name", description = "The name of the user.") #Valid #RequestParam(value = "name", required = false) String name,
#Parameter(name = "UserPostRequest", description = "") #Valid #RequestBody(required = false) UserPostRequest userPostRequest
) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "{ \"name\" : \"John Doe\" }";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
If, however, I would like to return a ResponseEntity<String> this gives an error since UserPost200Response is not used.
For the path /getuser, where the String response is first defined in the yaml file, my API looks like this:
default ResponseEntity<String> getuserPost(
#Parameter(name = "name", description = "The name of the user.") #Valid #RequestParam(value = "name", required = false) String name,
#Parameter(name = "UserPostRequest", description = "") #Valid #RequestBody(required = false) UserPostRequest userPostRequest
) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "\"John Doe\"";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
This API makes it possible to return a ResponseEntity<String> but not a ResponseEntity<UserPost200Response> which defines the above mentioned json-model.
One workaround that I found, would be to use the path where the string-response is declared first in the yaml file (see /getuser) in the example above and that returns a ResponseEntity<String> and override and do something like this:
default ResponseEntity<String> getuserPost(
#Parameter(name = "name", description = "The name of the user.") #Valid #RequestParam(value = "name", required = false) String name,
#Parameter(name = "UserPostRequest", description = "") #Valid #RequestBody(required = false) UserPostRequest userPostRequest
) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "{ \"name\" : \"John Doe\" }";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
if (mediaType.isCompatibleWith(MediaType.valueOf("text/plain"))) {
String exampleString = "John Doe";
ApiUtil.setExampleResponse(request, "text/plain", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
In this case, I don't use the Model created by the openapi-generator and treat the JSON basically as a string.
Another option is to go for a wildcard like ResponseEntity<?> but from what I understand, except proven the contrary, this seems bad practice. I haven't figured out how to declare this in the .yml file that is used by the openapi-generator.
Neither options seem to respect the contract.
I wonder if (1) I am doing something wrong here and (2) how it could be better implemented. The goal is of course to not rewrite the API's and only implement the logic in the Controllers. Any ResponseEntity in the API's should thus not be changed.
I have two variables of class User as follows:
val user1 = User().apply {....values here}
val user2 = User().apply {....values here}
I want to create a JsonNode with the following structure:
var node:JsonNode? = null
node = {
"user_1": {
...the fields of class User, assigned in variable user1
},
"user_2": {
...the values for user 2
}
}
I have converted the objects to nodes, but I do not know how to merge them using Jackson.
val mapper1= ObjectMapper()
mapper1.valueToTree<JsonNode>(user1)
val mapper2= ObjectMapper()
mapper2.valueToTree<JsonNode>(user2)
Or is there a more efficient way to create one json node structure with the two classes ?
I am using Kotlin and Jackson databank.
I haven't tested it, but I guess you should be able to simply create a Map<String, User> and convert that into a JsonNode:
val user1 = User().apply {....values here}
val user2 = User().apply {....values here}
val both = mapOf("user1" to user1, "user2" to user2)
val mapper = ObjectMapper()
val result = mapper.valueToTree<JsonNode>(both)
I'm using Spring Data + Jooq DSL. As result entity I'm using not jooq generated entity, but simple one, without any annotations and for relations One To Many getting result:
[{
"id":2,
"name":"James",
"addresses":[
{
"id":null,
"country":null,
"street":null
}
]
}]
Is any way to return an empty array for addresses?
My code to perform a request:
public Set<User> getUserById(Set<Long> id) {
Set<User> result = new HashSet<>();
ResultQuery users = dsl.select(
field("u.id", Long.class).as("id"),
field("u.name", String.class).as("name"),
field("a.id", Long.class).as("addresses_id"),
field("a.country", String.class).as("addresses_country"),
field("a.street", String.class).as("addresses_street")
).from("schema.user_table u")
.leftJoin("schema.address_table a")
.on("u.id = a.user_id")
.where(field("u.id").in(id));
try(ResultSet rs = users.fetchResultSet()) {
JdbcMapper<User> mapper = JdbcMapperFactory
.newInstance()
.addKeys("id")
.newMapper(User.class);
result = mapper.stream(rs).collect(Collectors.toSet());
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
Why not just use SQL/JSON to produce JSON documents directly from within your database?
public String getUserById(Set<Long> id) {
return dsl.select(coalesce(jsonArrayAgg(
jsonObject(
key("id").value(field("u.id", Long.class)),
key("name").value(field("u.name", String.class)),
key("addresses").value(coalesce(
jsonArrayAgg(jsonObject(
key("id").value(field("a.id", Long.class)),
key("country").value(field("a.country", String.class)),
key("street").value(field("a.street", String.class))
)),
jsonArray()
))
),
jsonArray()
)))
.from("schema.user_table u")
.leftJoin("schema.address_table a")
.on("u.id = a.user_id")
.where(field("u.id").in(id))
.fetchSingle().value1().data();
}
If you really need the intermediate User representation, then you can either:
Use Jackson or Gson to map the JSON document to the nested User DTO structure using reflection (works with jOOQ 3.14)
Use jOOQ 3.15's new MULTISET value constructor operator or MULTISET_AGG aggregate function along with ad-hoc converters, see below:
public Set<User> getUserById(Set<Long> id) {
return dsl.select(
field("u.id", Long.class),
field("u.name", String.class),
multisetAgg(
field("a.id", Long.class),
field("a.country", String.class),
field("a.street", String.class)
).convertFrom(r -> r == null
? Collections.<Address>emptyList()
: r.map(Records.mapping(Address::new)))
)
.from("schema.user_table u")
.leftJoin("schema.address_table a")
.on("u.id = a.user_id")
.where(field("u.id").in(id))
.fetchSet(Records.mapping(User::new));
}
Side note on code generation and execution
While not strictly relevant to this question, unless your schema is dynamic (not known at compile time), I really urge you to reconsider using source code generation. If you're not using it, you're missing out on a lot of jOOQ API advantages, just like when you're executing a jOOQ query with something other than jOOQ.
For me worked specify as a key addressId:
.addKeys("id", "addresses_id")
I have a method in a controller
#PostMapping("/process")
suspend fun process(
#RequestParam("id") id: String,
#RequestParam("names") names: List<String>,
#RequestParam("repositoryUri") repositoryUri: String
) = coroutineScope {
...
}
I want to send post query from front-end desktop application and I try
val post = HttpPost(uri)
val builder: MultipartEntityBuilder = MultipartEntityBuilder.create()
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
builder.addTextBody("id", id, ContentType.DEFAULT_BINARY) // id is String, that is Ok
builder.addTextBody("names", names, ContentType.DEFAULT_BINARY) // names is List<String>, error
builder.addTextBody("repositoryUri", repositoryUri, ContentType.DEFAULT_BINARY) // Ok
val entity: HttpEntity = builder.build()
post.entity = entity
httpclient.execute(post)
But the second param in the controller method (names) is not a string.
The builder has only methods addTextBody and addBinaryBody (but it doesn't seem to fit)
How can I do it?
P.S. I use apache
You'll need a custom format for sending a stringlist as a http form param.
Convert the list e.g. to a comma separated string, you'll have to reconvert the string to a list on the server side.
Or us json:
ObjectMapper mapper = new ObjectMapper();
TextBody("names", mapper.writeValueAsString(names), ... )
I am looking for a way to have a list of returned from a MySQL query, output in JSON with the field names instead of as an array. Here is some sample code:
List list = lookup_mgr.getResults("select someField, anotherField from someTable");
if (list != null) {
String json = new Gson().toJson(list);
}
This pulls a list and creates a JSON array like:
[
["someFieldValue","anotherFieldValue"],
["someFieldValue","anotherFieldValue"]
]
I'd like it to be like:
[
{
someField: "someFieldValue",
anotherField: "anotherFieldValue"]
},
{
someField: "someFieldValue",
anotherField: "anotherFieldValue"]
}
]
I am looking to keep it as simple and fast as possible. How would I go about doing that?
I think what you actually want is this ('{', '}' for objects):
[
{
someField: "someFieldValue",
anotherField: "anotherFieldValue"]
},
{
someField: "someFieldValue",
anotherField: "anotherFieldValue"]
}
]
This represents an array of objects in JSON notation. As opposed to what you currently get (an array of arrays of strings).
And to get that, you should create a Java bean class, that has exactly those two properties (let's call it SomeBean). Iterate over your query results and put the data you need in a List<SomeBean>, then pass that list to new Gson().toJson(list).
You can use JSONObject. Simply put your result into it and return that.
Example -
public JSONObject getResult(){
JSONObject responseJson = new JSONObject();
List<Object> resultList = new ArrayList<Object>();
User user1 = new User();
User user2 = new User();
User user3 = new User();
resultList.add(user1);
resultList.add(user2);
resultList.add(user3);
responseJson.put("result", resultList);
return responseJson;
}
Hope it helps!