Anyone knows - How to convert JSONObject to POJO class?
I have created an Adapter which i would like to convert it to Pojo before i send it to Client.
1) my ResourceAdapterResource.java (Adapter)
#POST
#Path("profiles/{userid}/{password}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public JSONObject getStatus(#PathParam("userid") String userid, #PathParam("password") String password) throws IOException {
Map<String, Object> maps = new HashMap<String,Object>();
map.put("userid", userid);
map.put("password",password);
// json Object will get the value from SOAP Adapter Service
JSONObject obj = soapAdapterService(maps);
/** Question here, how to add to POJO.. I have code here but not work, null values**/
// set to Object Pojo Employee
Employee emp = new Employee();
emp.setUserId(String.valueOf(obj.get("userId")));
emp.setUserStatus((String.valueOf(obj.get("userStatus")));
// when I logging its show Empty.
logger.info("User ID from service : " + emp.getUserId());
logger.info("Status Id from service : " + emp.getUserStatus());
return obj;
}
2.) Pojo Class - Employee
import java.io.Serializable;
#SuppressWarnings("serial")
public class Employee implements Serializable{
private String userid;
private String userStatus;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid= userid;
}
public String getUserStatus() {
return userStatus;
}
public void setUserStaus(String userStatus) {
this.userStatus= userStatus;
}
}
When I tested using Swagger - MobileFirst Console restful testing, it return the JsonObject with successfully return Body with data from the services.
But when i check log info ( message.log ) - server logs, the status is null.
User ID from service : null
Status Id from service : null
Seems its JSON Java IBM API , does it have ObjectMapper like Jackson API to map the JsonObject to POJO Class.
Results from Swagger
{
"statusReason": "OK",
"responseHeaders": {
"Content-Length": "1849",
"Content-Language": "en-US",
"Date": "Thu, 23 Mar 2017 01:40:33 GMT",
"X-Powered-By": "Servlet/3.0",
"Content-Type": "text/xml; charset=utf-8"
},
"isSuccessful": true,
"responseTime": 28,
"totalTime": 33,
"warnings": [],
"Envelope": {
"soapenv": "http://schemas.xmlsoap.org/soap/envelope/",
"Body": {
"checkEmployeeLoginResponse": {
"a": "http://com.fndong.my/employee_Login/",
"loginEmployeeResp": {
"Employee": {
"idmpuUserName": "fndong",
"Status": "A",
"userid": "fndong",
"Password": "AohIeNooBHfedOVvjcYpJANgPQ1qq73WKhHvch0VQtg#=",
"PwdCount": "1",
"rEmail": "fndong#gmail.com"
},
"sessionId": "%3F",
"statusCode": "0"
}
}
}
},
"errors": [],
"info": [],
"statusCode": 200
}
Then I followed your suggestion to cast to String:
String objUserId = (String) objectAuth.get("userid");
The Results still null, does it require to indicate the json restful result by call the body function "loginEmployeeResp", because the data JSon Object are from service SOAP.
Clearly your String.valueOf(obj.get("userId")) is returning null or empty, so the question is, which part of it?
You can log obj.get("userId") and see if that is empty, in which case the response doesn't contain what you expect.
But I suspect the issue is the String.valueOf() conversion not doing what you expect. It looks like the JSONObject in MobileFirst is com.ibm.json.java.JSONObject, and when I search on that, the example I found simply casts to String:
emp.setUserId((String) obj.get("userId"));
Edit: now that you've added the Swagger results, I'd say your obj.get("userId") probably is returning null itself. Did you check that?
For one thing, "userId" isn't "userid". The capitalization matters.
But more importantly, "userid" is nested deep in the JSON, so I don't think just getting it from the top level JSONObject is going to work. I think you'll have to do something like:
JSONObject envelope = (JSONObject) obj.get("Envelope");
JSONObject body = (JSONObject) envelope.get("Body");
JSONObject response = (JSONObject) body.get("checkEmployeeLoginResponse");
JSONObject resp = (JSONObject) response.get("loginEmployeeResp");
JSONObject employee = (JSONObject) resp.get("Employee");
emp.setUserId((String) employee.get("userid"));
emp.setUserStatus((String) employee.get("status"));
(Regrettably, with that particular IBM JSON4J, I don't think there's a way to do a more automatic unmarshalling of JSON into Java objects.)
Related
It seems there exists a difference in the way of deserialization process of Newtonsoft.Json.6.0.8 vs Newtonsoft.Json.12.0.3.
The following is model in our C# project :
public class WebServiceConfigModel
{
public string RestoreFile { get; set; }
public string RestoreFileDescription { get; set; }
}
The action method defined in the controller is as follows:
[HttpPost]
public void Restore(WebServiceConfigModel request)
{
}
The input JSON text which was provided to the method is as follows:
{
"RestoreFile": "SampleFile",
"RestoreFileDescription": {
"ID": "DatasetDescription",
"Label": "Description"
}
}
This was deserialized successfully (the request object contains values), even if there exists a deserialization error and we were able to read the RestoreFile property value in the C# while using the Newtonsoft.Json.6.0.8.
After upgrading the version Newtonsoft.Json to 12.0.3, the request object in C# seems to be null and the deserialization error still exists. It works properly if we change the "RestoreFileDescription" property to a string value.
Is there any way to get the deserialized object even if some of the property has a contract mismatch?
These docs may be helpful.
It appears that as of 12.0.1, you can handle Json Deserialization errors in two ways:
JsonSerializerSettings.Error event
The [OnError] attribute
In the first instance, the JsonSerializerSettings have been set so as to handle a non-date string, and this is handled as per their docs:
The event handler has logged these messages and Json.NET has continued on deserializing the JSON because the errors were marked as handled.
List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(#"[
'2009-09-09T00:00:00Z',
'I am not a date and will error!',
[
1
],
'1977-02-20T00:00:00Z',
null,
'2000-12-01T00:00:00Z'
]",
new JsonSerializerSettings
{
Error = delegate(object sender, ErrorEventArgs args)
{
errors.Add(args.ErrorContext.Error.Message);
args.ErrorContext.Handled = true;
},
Converters = { new IsoDateTimeConverter() }
});
The second way is to create a method, and decorate it with the [OnError] attribute as follows:
[OnError]
internal void OnError(StreamingContext context, ErrorContext errorContext)
{
errorContext.Handled = true;
}
PersonError person = new PersonError
{
Name = "George Michael Bluth",
Age = 16,
Roles = null,
Title = "Mister Manager"
};
So when Roles is required, this provides the following result:
string json = JsonConvert.SerializeObject(person, Formatting.Indented);
Console.WriteLine(json);
//{
// "Name": "George Michael Bluth",
// "Age": 16,
// "Title": "Mister Manager"
//}
I'm still pretty new to programming with Kotlin but I can't seem to figure out the correct way to parse my JSON. I'm attempting to get "title" and "body" from "notification" in "unackd" array only.
So far I've got:
private fun parse(): Boolean {
try {
val ja = JSONArray(jsonData)
var jo: JSONObject
users.clear()
var user: User
for (i in 0 until ja.length()) {
jo = ja.getJSONObject(i)
val name = jo.getString("title")
val username = jo.getString("body")
user = User(username,name)
users.add(user)
}
return true
} catch (e: JSONException) {
e.printStackTrace()
return false
}
}
Meanwhile my JSON is structured as so:
{
"unackd": [
{
"notification": {
"title": "Title Test Number 200",
"body": "passage local they water difficulty tank industry allow increase itself captured strike immediately type phrase driver change save potatoes stems addition behavior grain trap rapidly love refused way television bright 1100"
},
"data": {
"id": "1100",
"phone": "+15555551234"
}
},
{
"notification": {
"title": "Title Test Number 199",
"body": "announced beside well noted mysterious farm he essential likely deeply vast touch 1099"
},
"data": {
"id": "1099",
"phone": "+15555551234"
}
}
],
"ackd": [
{
"notification": {
"title": "Title Test Number 200",
"body": "passage local they water difficulty tank industry allow increase itself captured strike immediately type phrase driver change save potatoes stems addition behavior grain trap rapidly love refused way television bright 1100"
},
"data": {
"id": "1100",
"phone": "+15555551234"
}
},
{
"notification": {
"title": "Title Test Number 199",
"body": "announced beside well noted mysterious farm he essential likely deeply vast touch 1099"
},
"data": {
"id": "1099",
"phone": "+15555551234"
}
}
]
}
I believe my issue is getting into "notification" to then get the strings "title" and "body". Which I've tried
test1 = jo.getJSONObject("notification")
Any help would be appreciated!
EDIT:
This is my logcat error, I assume it has to do with the JSON.typeMismatch:
at org.json.JSON.typeMismatch(JSON.java:111)
at org.json.JSONArray.<init>(JSONArray.java:96)
at org.json.JSONArray.<init>(JSONArray.java:108)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
The exception message suggests that you're passing data that doesn't represent a JSON array when instantiating JSONArray:
at org.json.JSON.typeMismatch(JSON.java:111)
at org.json.JSONArray.<init>(JSONArray.java:96)
The JSON you've attached is in fact a JSON object, notice that its content is enclosed in {}. Hence to access the "unackd" array, you need to first create a JSON object, and then reference the array inside of it:
val root = JSONObject(jsonData)
val ja = root.getJSONArray("unackd")
// the rest of your code goes here
Listen friend , parsing the JSON Object with JSON ARRAY with key (like: unackd , ackd) is so simple.
There are 2 ways:
1st Way)
Parse your JSON to Pojo schema
http://www.jsonschema2pojo.org/
public class Ackd {
#SerializedName("notification")
#Expose
private Notification_ notification;
#SerializedName("data")
#Expose
private Data_ data;
public Notification_ getNotification() {
return notification;
}
public void setNotification(Notification_ notification) {
this.notification = notification;
}
public Data_ getData() {
return data;
}
public void setData(Data_ data) {
this.data = data;
}
}
public class Data {
#SerializedName("id")
#Expose
private String id;
#SerializedName("phone")
#Expose
private String phone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
No need to Make all class for parsing (like ackd (Json Array))
2nd Way)
You need to PARSE JSON array with name only unackd not ackd.
String jsonStr = sh.makeServiceCall(url);
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray unA= jsonObj.getJSONArray("unackd");
for (int i = 0; i < unA.length(); i++)
{
JSONObject c = unA.getJSONObject(i);
String title= c.getString("title");
String body= c.getString("body");
}
Auto generate Data class
http://www.jsonschema2pojo.org/
I suppose that your class is named Response.java
Response object=new Gson().fromjson(jsonContentFile,Response.class);
Following data classes are generated for your JSON using https://json2kotlin.com
data class Json4Kotlin_Base (
val unackd : List<Unackd>,
val ackd : List<Ackd>
)
and
data class Data (
val id : Int,
val phone : Int
)
and
data class Notification (
val title : String,
val body : String
)
and
data class Ackd (
val notification : Notification,
val data : Data
)
and
data class Unackd (
val notification : Notification,
val data : Data
)
Here's a video that explains how to implement these when generated.
I am fairly new to JAX-RS so bear with me on this question. I'm trying to consume a REST API using JAX-RS framework. In particular I am trying to invoke a HTTP GET method on a resource where the response entity will be in JSON format. Up until now I can parse the returned JSON into a customized class with the following code snippet;
WebTarget target = client.target(url);
Builder builder = target.request(MediaType.APPLICATION_JSON);
myClass obj = builder.get(myClass.class);
However, in my latest GET request the JSON return will be best abstracted as a collection of objects. I know in .NET this can be done fairly easily with
JsonConvert.DeserializeObject<List<myClass>>
but how could I do that in JAX-RS? Thanks in advance.
EDIT:
I model my code after the solution in How to get list<String> as response from jersey2 client
WebTarget target = client.target(url);
Builder builder = target.request(MediaType.APPLICATION_JSON);
builder.header(X_OCTOPUS_APIKEY_NAME, apiKey);
Response serviceResponse = builder.get(Response.class);
List<myType> objects = serviceResponse.readEntity(new GenericType<List<myType>>() {});
However the objects returned is always null. To verify the REST API call actually return a valid JSON value I replace the last line with:
String strDate = serviceResponse.readEntity(String.class);
It is confirmed with the following JSON return:
[
{
"Id": "Users-267",
"Username": "mdamon#mydomain.com",
"DisplayName": "Damon, Matt",
"IsActive": true,
"IsService": false,
"EmailAddress": "mdamon#mydomain.com",
"IsRequestor": false,
"Links": {
"Self": "/api/users/Users-267",
"Permissions": "/api/users/Users-267/permissions",
"ApiKeys": "/api/users/Users-267/apikeys{/id}{?skip}",
"Avatar": "https://www.gravatar.com/avatar/94324e7c54a9a5f9d103b2a709863fc3?d=blank"
}
},
{
"Id": "Users-2101",
"Username": "baffleck#mydomain.com",
"DisplayName": "Affleck, Ben",
"IsActive": true,
"IsService": false,
"EmailAddress": "baffleck#mydomain.com",
"IsRequestor": false,
"Links": {
"Self": "/api/users/Users-2101",
"Permissions": "/api/users/Users-2101/permissions",
"ApiKeys": "/api/users/Users-2101/apikeys{/id}{?skip}",
"Avatar": "https://www.gravatar.com/avatar/11edd32712facde9a7d3dd4445a4abe9?d=blank"
}
},
...
]
So for reason the JSON is not being parsed at a collection of my custom type. One extra piece of information is my custom is defined as follows:
#XmlRootElement
public class myType {
String DisplayName;
String EmailAddress;
public myType() {
super();
}
public void setDisplayName(String displayName) {
DisplayName = displayName;
}
public String getDisplayName() {
return DisplayName;
}
public void setEmailAddress(String emailAddress) {
EmailAddress = emailAddress;
}
public String getEmailAddress() {
return EmailAddress;
}
}
I only include the DisplayName and EmailAddress field of the JSON in my custom type because I don't need all the other data, in case that matters. Can anyone tell me why it is not being parsed? Thanks
I have JSON response from WS:
[
{
"name": "Bobby",
"status": "single"
},
{
"name": "John",
"status": "married"
}
]
Here is my wrapper
#XmlRootElement(name = "users")
public class UserListWrapper {
private List<User> users;
#XmlElement(name = "user")
public List<User> getUsers() {
return users;
}
// getters and setters omitted
}
And User class
#XmlRootElement
class User {
private String name;
private String status;
// getters and setters omitted
}
The problem is when Jersey try to deserialize response to my wrapper object. It say
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of com.jersey.test.UserListWrapper out of START_ARRAY token
Seams that something wrong with my wrapper annotations. How can I fix them?
UPD
When I send
{
"user": [
{
"name": "Bob",
"status": "single"
},
{
"name": "Mike",
"status": "married"
}
]
}
all works fine. But I need this format
[
{
"name": "Bobby",
"status": "single"
},
...
]
UPD
Jersey Client code
HttpAuthenticationFeature authenticationFeature = HttpAuthenticationFeature.basic("user", "secret");
Client client = ClientBuilder
.newClient()
.register(authenticationFeature)
.register(JacksonFeature.class);
WebTarget target = client.target("http://localhost:8080/server/");
UserListWrapper entity;
Response resp;
resp = target.queryParam("u", "info")
.path("/rest/users")
.request()
.accept(APPLICATION_JSON)
.get();
entity = resp.readEntity(UserListWrapper.class);
Forget the UserListWrapper wrapper then. List<User> is perfect for the JSON array ( [] ) format. If you add the wrapper class, then yes you will need the extra JSON object layer ( {} ). This:
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response createBook(List<User> users) {
is supported just fine (at least with Jackson - which you are using).
UPDATE
If the response from the server is coming as a JSON array, then you can still deserialize it as a List<User>. For example
WebResource resource = client.resource("...");
List<User> users = resource.get(new GenericType<List<User>>(){});
See this related post
UPDATE 2
Since you are using the JAX-RS 2 client API, you can use the overloaded readEntity, which accepts a GenericType argument also
List<User> user = response.readEntity(new GenericType<List<User>>(){});
I have a project using MVC4, i want to ask how to get data from webapi and return into view.
Model
public class Name
{
public Int32 NameId { get; set; }
public String FirstName{ get; set; }
public String LastName{ get; set; }
public String CreatedBy { get; set; }
}
public class IListMyProject
{
public List<Name> Names { get; set; }
}
I can list all in my Index.cshtml using this code
public ActionResult Index()
{
string securityToken = repo.GetTokens();
if (securityToken != null)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "webapiurl/api/Name/Get?$orderby=LastName&$top=10");
string authHeader = System.Net.HttpRequestHeader.Authorization.ToString();
httpRequestMessage.Headers.Add(authHeader, string.Format("JWT {0}", securityToken));
var response = client.SendAsync(httpRequestMessage)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode())
.Result;
if (response.IsSuccessStatusCode)
{
model.Names = response.Content.ReadAsAsync<IList<Name>>().Result.ToList();
}
}
return View("Index", model);
}
i can return my view. and now i have another view called Details.cshtml with this code :
public ActionResult Details(string id)
{
string securityToken = repo.GetTokens();
if (securityToken != null)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "webapiurl/api/Name/GetById/"+id+"");
string authHeader = System.Net.HttpRequestHeader.Authorization.ToString();
httpRequestMessage.Headers.Add(authHeader, string.Format("JWT {0}", securityToken));
var response = client.SendAsync(httpRequestMessage)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode())
.Result;
if (response.IsSuccessStatusCode)
{
model.Names = response.Content.ReadAsAsync<IList<Name>>().Result.ToList();
}
}
return View(model);
}
For this Detail, my Json looks like this:
application/json, text/json
{
"NameId": 1,
"FirstName": "This is First Name",
"LastName": "This is Last Name",
"CreatedBy": "This is Created By"
}
when i run it, i get this error :
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IList`1[Models.Name]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'NameId', line 1, position 10.
How do i fix this, im new to webapi. i wonder why do if i list all (for index, i use api/get) it works, but when i want to show it in detail, it doesn't work.
thank for help
Regards
EDIT
when i debug in
model.Names = response.Content.ReadAsAsync<IList<Name>>().Result.ToList();
its says Null, is there something wrong when i try to get the response ?
The issue is that:
{
"NameId": 1,
"FirstName": "This is First Name",
"LastName": "This is Last Name",
"CreatedBy": "This is Created By"
}
can't be deserialized as an IList. The JSON you have above is just one name, not a collection of Names. So Json.NET deserialization will fail.
Make sure that your Web API controller returns an IList, or change your MVC code to read the content as a single Name. A collection of names in JSON would look like this instead:
[{
"NameId": 1,
"FirstName": "This is First Name",
"LastName": "This is Last Name",
"CreatedBy": "This is Created By"
},
{
"NameId": 2,
"FirstName": "This is First Name",
"LastName": "This is Last Name",
"CreatedBy": "This is Created By"
}]
The Web API is returning a single object of type Name, not a collections of Name. I do not see where you define model. I added a definition of type Name. Try this.
public ActionResult Details(string id)
{
string securityToken = repo.GetTokens();
Name model;
if (securityToken != null)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "webapiurl/api/Name/GetById/"+id+"");
string authHeader = System.Net.HttpRequestHeader.Authorization.ToString();
httpRequestMessage.Headers.Add(authHeader, string.Format("JWT {0}", securityToken));
var response = client.SendAsync(httpRequestMessage)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode())
.Result;
if (response.IsSuccessStatusCode)
{
model = response.Content.ReadAsAsync<Name>();
}
}
return View(model);
}
The issue seems to be the fact that your JSON returns only 1 record while you are Reading the result as IList<Name>. Changing it to simply Name should fix the problem.
However you question is: "how to call web api in controller and return into view MVC4"
I recommend you to look at http://restsharp.org/ You can simplify your code to:
public ActionResult Details(string id)
{
string securityToken = repo.GetTokens();
Name model;
if (securityToken != null)
{
var client = new RestClient("");
var request = new RestRequest("webapiurl/api/Name/GetById/"+id, HttpMethod.Get);
string authHeader = System.Net.HttpRequestHeader.Authorization.ToString();
request.AddHeader(authHeader, string.Format("JWT {0}", securityToken));
var model = client.Execute<Name>(request);
}
return View(model);
}