I need to send data to database in this format -
{"param1":"value1", "param2":"value2", "param3": {"username": "admin", "password": "123"}}
How to generate this using JSONStringer ?
I tried this -
vm = new JSONStringer().object().key("param1").value("value1")
.object().key("param2").value("value2")
.key("param3").object()
.key("username").value("admin")
.key("password").value("123")
.endObject().endObject().endObject();
But I'm getting this error -
org.json.JSONException: Nesting problem at
org.json.JSONStringer.beforeValue(JSONStringer.java:415)
JSONObject object1 = new JSONObject();
object1.put("param1", "value1");
object1.put("param2", "param2");
JSONObject innerObject1 = new JSONObject();
innerObject1.put("username", "admin");
innerObject1.put("password", "123");
object1.put("param3",innerObject1);
String jsonStr = object1.toString();
Ideally reverse of JSON parsing can be applied to create a json string object, so that the same can be send to Server/DB
Try this
try {
JSONObject object=new JSONObject();
object.put("param1","value1");
object.put("param2","value2");
JSONObject param3=new JSONObject();
paraam3.put("username","admin");
paraam3.put("password","123");
object.put("param3",param3);
} catch (JSONException e) {
e.printStackTrace();
}
You can create model which will be your java file same as your JSON file and can use gson library which is supported by Google to do JSON parsing. The library is quite flexible and easy to use then using traditional method of JSON parsing.
Model File
public class Response {
public String param1;
public String param2;
public Param3 param3;
public Response(String param1, String param2) {
this.param1 = param1;
this.param2 = param2;
}
public class Param3 {
public String username;
public String password;
public Param3(String username, String password) {
this.username = username;
this.password = password;
}
}
}
In file in which you insert data
Response res = new Response("value1", "value2", new Param3("admin","123"));
String dbResult = new Gson.toJson(res);
If you are looking for the actual solution using org.json.JSONStringer
JSONWriter writer = stringer3.object()
.key("param1").value("value1")
.key("param2").value("value2")
.key("param3").object()
.key("username").value("admin")
.key("password").value("123")
.endObject()
.endObject();
System.out.println(writer.toString());
You can think of the object() method as opening a new parenthesis and the endObject() as closing it
Related
I'm having a trouble with my Java application receiving Spotify API auth tokens and mapping them to POJO with Jackson.
Every time my app requests data from Spotify API, I start with getting a new access token from this link: https://accounts.spotify.com/api/token?grant_type=client_credentials
and the answer is JSON, that looks like this:
{
"access_token":"BQAJmzZOdh2egvWEOEwy4wv-VKdhTUc4eZYJrIfAibjWLR4MPfrbV6KBNIiomPwJKsQN-3vmrGmG7lOXFaI",
"token_type":"Bearer",
"expires_in":3600,
"scope":""
}
Every time I launch my app, the first time it works nice, but then it crashes with:
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.slowedandthrowed.darkjazzbot.mapping.spotify.TokenRequest` (although at least
one Creator exists): no String-argument constructor/factory method to deserialize from String value ('BQCcDMOKUiVPscDrrBH77b2QbN9FuqjAJHuM3_1QD39MO9L20XzXneZUlJeIyukBVhPpaCWnKWRjUdggaCM') at [Source: (String)"{"access_token":"BQCcDMOKUiVPscDrrBH77b2QbN9FuqjAJHuM3_1QD39MO9L20XzXneZUlJeIyukBVhPpaCWnKWRjUdggaCM","token_type":"Bearer","expires_in":3600,"scope":""}"; line: 1, column: 17]
I kinda duct taped this problem by creating a new ObjectMapper every time I need to map access token JSON to POJO, but if it would be a production app, it would harm the performance, so I need to find out whats the problem in using one ObjectMapper instance for all the time.
I also tried to map this JSON to Map<String,String> instead of mapping it to TokenRequest.class and the result was the same, so I don't think that this is the reason why mapping fails.
private String requestAccessToken() throws IOException {
TokenRequest tokenRequest = null;
URL accessTokenUrl = new URL(SPOTIFY_TOKEN_LINK);
HttpURLConnection tokenConnection = (HttpURLConnection) accessTokenUrl.openConnection();
tokenConnection.setRequestProperty("Authorization", authString);
tokenConnection.setDoOutput(true);
tokenConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
tokenConnection.setRequestMethod("POST");
OutputStreamWriter wr = new OutputStreamWriter(tokenConnection.getOutputStream());
wr.write(TOKEN_REQUEST_PARAMETERS);
wr.flush();
System.out.println("Wow! Posted!");
InputStream inputStream = tokenConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
StringBuilder inputBuilder = new StringBuilder();
String input = null;
while ((input = reader.readLine()) != null) inputBuilder.append(input);
System.out.println("================================= TOKEN INPUT ======================================");
System.out.println(inputBuilder.toString());
System.out.println("================================= TOKEN INPUT ======================================");
tokenRequest = spotifyObjectMapper.readValue(inputBuilder.toString(), TokenRequest.class);
inputStream.close();
reader.close();
tokenConnection.disconnect();
return tokenRequest.getAccessToken();
}
TokenRequest.java:
package com.slowedandthrowed.darkjazzbot.mapping.spotify;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonRootName;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"access_token",
"token_type",
"expires_in",
"scope"
})
#JsonRootName("access_token")
public class TokenRequest {
#JsonProperty("access_token")
private String accessToken;
#JsonProperty("token_type")
private String tokenType;
#JsonProperty("expires_in")
private Long expiresIn;
#JsonProperty("scope")
private String scope;
#JsonProperty("access_token")
public String getAccessToken() {
return accessToken;
}
#JsonProperty("access_token")
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
#JsonProperty("token_type")
public String getTokenType() {
return tokenType;
}
#JsonProperty("token_type")
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
#JsonProperty("expires_in")
public Long getExpiresIn() {
return expiresIn;
}
#JsonProperty("expires_in")
public void setExpiresIn(Long expiresIn) {
this.expiresIn = expiresIn;
}
#JsonProperty("scope")
public String getScope() {
return scope;
}
#JsonProperty("scope")
public void setScope(String scope) {
this.scope = scope;
}
}
I fixed my program because i created the problems for myself.
I recieved different data thru different APIs and mapped it to a POJOs via single instance of Jackson ObjectMapper. Some JSON object contain data by themself:
{
"property1":value1,
"property2":value2
}
While other had single nested object with data inside:
{
"object":{"property1":value1,
"property2":value2
}}
So i decided to turn UNWRAP_ROOT_VALUE to TRUE and then my object mapper changed its state so its behavior became different between my first and second attempt to recieve access token.
For a Json body like
{
"firstName": "hello",
"lastName": "abc"
}
I am writing as
JSONObject body = new JSONObject();
body.put("firstName", "hello");
body.put("lastName", "abc");
and then converting body to string to pass it as string parameter
How can I write the same for body with response like
{
"class": {
"firstName": "hello",
"lastName": "abc"
}
}
I need to convert json to string afterwards
I think this should do the trick
JSONObject innerBody = new JSONObject();
innerBody.put("firstName", "hello");
innerBody.put("lastName", "abc");
JSONObject outerBody = new JSONObject();
outerBody.put("class",innerBody);
Create a class:
public class DataSource {
private String firstName;
private String lastName;
//Constructor, getter, setter
}
And then:
JSONObject body = new JSONObject();
DataSource data = new DataSource();
data.setFirstName("bla");
data.setLastName("bla bla");
body.put("class", data );
I'm trying to Parse very simply JSON to object (with GSON)
My JSON:
[{"username":"admin","password":"admin","name":"admin","email":"admin#admin.com"},{"username":"mark20","password":"mark123","name":"mark","email":"mark#steew.com"}]
is there 2 users, so I create 2 class, Users with list of users and User :
public class Users {
ArrayList<User> users;
Users(ArrayList<User> users){
this.users = users;
}
}
.
public class User {
String userame;
String password;
String name;
String email;
}
and here is my parsing code:
public void onResponse(Call call, Response response) throws IOException {
String body = response.body().string();
Gson gson = new GsonBuilder().create();
Users users = gson.fromJson(body, Users.class);
}
of course in variable body I have got correct JSON, but in last lane I got:
JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
What can be wrong here ? How to fix it ?
Your json is an array of User not a wrapper Users of array User.
Read your json like this:
User[] users = gson.fromJson(body, User[].class);
If you want an ArrayList<>:
List<User> userList = Arrays.asList(users);
Another way is to use TypeToken:
Type listType = new TypeToken<ArrayList<User>>(){}.getType();
List<User> userList = gson.fromJson(body, listType);
If I'm reading from what I read elsewhere correctly try:
public void onResponse(Call call, Response response) throws IOException {
String body = response.body().string();
Gson gson = new GsonBuilder().create();
User[] users = gson.fromJson(body, User[].class);
}
I have a response object like this:
public class TestResponse {
private final String response;
private final ErrorCodeEnum error;
private final StatusCodeEnum status;
// .. constructors and getters here
}
I am serializing above class using Gson library as shown below:
Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
System.out.println(gson.toJson(testResponseOutput));
And the response I am getting back is shown below:
{
"response": "{\"hello\":0,\"world\":\"0\"}",
"error": "OK",
"status": "SUCCESS"
}
As you can see, my json string in "response" field is getting escaped. Is there any way I can ask gson not to do that and instead return a full response like this:
{
"response": {"hello":0,"world":"0"},
"error": "OK",
"status": "SUCCESS"
}
And also - Is there any problem if I do it above way?
NOTE: My "response" string will always be JSON string or it will be null so only these two values will be there in my "response" string. In "response" field, I can have any json string since this library is calling a rest service which can return back any json string so I am storing that in a string "response" field.
If your response field can be arbitrary JSON, then you need to:
Define it as an arbitrary JSON field (leveraging the JSON type system already built into GSON by defining it as the root of the JSON hierarchy - JsonElement)
public class TestResponse {
private final JsonElement response;
}
Convert the String field to an appropriate JSON object representation. For this, you can use GSON's JsonParser class:
final JsonParser parser = new JsonParser();
String responseJson = "{\"hello\":0,\"world\":\"0\"}";
JsonElement json = parser.parse(responseJson); // Omits error checking, what if responseJson is invalid JSON?
System.out.println(gson.toJson(new TestResponse(json)));
This should print:
{
"response": {
"hello": 0,
"world": "0"
}
}
It should also work for any valid JSON:
String responseJson = "{\"arbitrary\":\"fields\",\"can-be\":{\"in\":[\"here\",\"!\"]}}";
JsonElement json = parser.parse(responseJson);
System.out.println(gson.toJson(new TestResponse(json)));
Output:
{
"response": {
"arbitrary": "fields",
"can-be": {
"in": [
"here",
"!"
]
}
}
}
I know this is old but just adding an potential answer in case it is needed.
Sounds like you just want to return the response without escaping. Escaping is a good thing, it will help to prevent security issues and prevent your JS application from crashing with errors.
However, if you still want to ignore escaping, try:
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().create();
add simple TypeAdapter and use jsonValue(value)
gson 2.8.0
version 1:
#Test
public void correctlyShow() {
TestResponse2 src = new TestResponse2("{\"arbitrary\":\"fields\",\"can-be\":{\"in\":[\"here\",\"!\"]}}");
Gson create = new GsonBuilder().registerTypeAdapter(String.class, ADAPTER).create();
Stopwatch createStarted = Stopwatch.createStarted();
String json2 = create.toJson(src);
System.out.println(json2 + " correctlyShow4 " + createStarted.stop());
}
public class TestResponse2 {
private final String response;
public TestResponse2(String response) {
this.response = response;
}
public String getResponse() {
return response;
}
}
private static final TypeAdapter<String> ADAPTER = new TypeAdapter<String>() {
#Override
public String read(JsonReader in) throws IOException {
throw new UnsupportedOperationException("Unsupported Operation !!!");
}
#Override
public void write(JsonWriter out, String value) throws IOException {
out.jsonValue(value);
}
};
...
vesrion 2
#Test
public void correctlyShow() {
TestResponse2 src = new TestResponse2("{\"arbitrary\":\"fields\",\"can-be\":{\"in\":[\"here\",\"!\"]}}");
String json2 = new Gson().toJson(src);
System.out.println(json2 + " correctlyShow4 ");
}
public class TestResponse2 {
#JsonAdapter(value = AdapterStringJson.class)
private final String response;
public TestResponse2(String response) {
this.response = response;
}
public String getResponse() {
return response;
}
}
private class AdapterStringJson extends TypeAdapter<String> {
#Override
public String read(JsonReader in) throws IOException {
throw new UnsupportedOperationException("Unsupported Operation !!!");
}
#Override
public void write(JsonWriter out, String value) throws IOException {
out.jsonValue(value);
}
}
You should have a nested object.
public class Response {
private final Integer hello;
private final String world;
}
public class TestResponse {
private final Response response;
private final ErrorCodeEnum error;
private final StatusCodeEnum status;
// .. constructors and getters here
}
Instead of a String, depending on your needs, you could use a Map (or similar) or a nested Object. There should not be a problem representing it this way but in your example, if it were a String, there would be a problem if you didn't escape characters such as the double-quote.
I'm making an inventory control. I was trying to check if the entered quantity of item is less than the stock quantity or not. I'm getting the servet json output. But I can't send it to jsp back.
Jsp JQuery code.
<script>
$('document').ready(function() {
$('#submit_btn').click((function() {
var $name = $("select#item_name").val();
var $qty = $("input#qty").val();
$.post('BuyItem', {item_name: $name, item_qty: $qty}, function(data) {
if (data !== null) {
alert(text(data));
$("input#qty").val("");
} else {
alert("Invalid Item!");
}
}
);
}));
});
</script>
And this is servlet query.
while (rs.next()) {
if (rs.getInt("qty") > qty) {
int id = rs.getInt("item_id");
Gson gson = new Gson();
String json = gson.toJson(id);
// System.out.println("one" + json);
response.setContentType("application/json");
// response.setCharacterEncoding("UTF-8");
response.getWriter().print(json);
} else {
Gson gson = new Gson();
String json = gson.toJson("Stock doesn\'t have enough item quantity.");
// System.out.println("two" + json);
response.setContentType("application/json");
// response.setCharacterEncoding("UTF-8");
response.getWriter().print(json);
}
}
From both System.out.println() s output is always coming correctly. But not sending to jsp back. Please help me with this.
what you have to do and also a best practice is to create a DTO class with the properties that you need to pass to gson library.
public class ResponseDTO implements Serializable{
private Integer id;
//more properties ...
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id= id;
}
// other getters & setters
}
and inside your loop, set the values to the dto object, then pass it to gson.
Gson gson = new Gson();
ResponseDTO dto = null;
String json = "";
response.setContentType("application/json");
......
if (rs.getInt("qty") > qty) {
dto = new ResponseDTO();
int id = rs.getInt("item_id");
dto.setId(id);
......
json = gson.toJson(dto);
} else {
...... // similar
json = gson.toJson("{data: 'Some message'}");
}
response.getWriter().print(json);
gson will give you the proper json structure to the client side.
try and see !
Gson allows strings and numbers to serialize to JSON by themselves (which is probably ok by the definition), but a lot of other libraries would consider this invalid JSON.
Try wrapping your response in an object so that the response is {"id": 5} and not just 5.