Resolving Nested JSON issue using Spring-Hibernate - json

I am using spring mvc and jackson for my extjs application and stuck at some thing similar.
I have my list of records returned from DB using Hibernate.
DAO class:
#SuppressWarnings("unchecked")
#Override
public List<CandidateStatus> getcandidateStatus() {
//return hibernateTemplate.find("select candstat.candidate.firstName as firstName,candstat.candidate.lastName as lastName,candstat.candidate.email as email,candstat.statusTitle as statusTitle,candstat.requirement.client.clientName as clientName,candstat.requirement.reqTitle as reqTitle from CandidateStatus as candstat");
return hibernateTemplate.find("from CandidateStatus");
//return hibernateTemplate.find("from CandidateStatus candstat left outer join candstat.candidate left outer join candstat.requirement left outer join candstat.requirement.client");
//return hibernateTemplate.find("from Candidates as cands inner join cands.candidateStats");
}
**Service class**
public List<CandidateStatus> getCandidateStatusList()
{
//return candidatesDAO.getCandidates();
return candidatesDAO.getcandidateStatus();
}
Controller class
#RequestMapping(value="/candidates/view.action")
public #ResponseBody Map<String,? extends Object> view() throws Exception {
try{
//List<Candidates> candidates = candidatesService.getCandidatesList();
List<CandidateStatus> candidatestatus = candidatesService.getCandidateStatusList();
return getMap(candidatestatus);
} catch (Exception e) {
return getModelMapError("Error retrieving Candidates from database.");
}
private Map<String,Object> getMap(List<CandidateStatus> candidatestatus){
Map<String,Object> modelMap = new HashMap<String,Object>(3);
modelMap.put("success", true);
modelMap.put("total", candidatestatus.size());
modelMap.put("data", candidatestatus);
return modelMap;
}
private Map<String,Object> getModelMapError(String msg){
Map<String,Object> modelMap = new HashMap<String,Object>(2);
modelMap.put("message", msg);
modelMap.put("success", false);
return modelMap;
}
Before adding it to the map I want to format the JSON in a required format as per my application.I get the format in a nested manner which is not accepted by extjs.
{
"data": [
{
"id": 29,
"requirement": {
"id": 27,
"client": {
"id": 12,
"clientName": "HireCraft"
},
"clientId": 12,
"reqTitle": "Support Engineer"
},
"reqid": 27,
"resid": 45,
"candidate": {
"id": 45,
"firstName": "Vikram",
"lastName": "",
"email": "bj.vikram#gmail.com"
},
"statusTitle": "Shortlisted"
}],
"success":true,
"total":7668
}
I want the json to be flat file like this without nesting.
"data": [ {
"clientName": "ABC"
"firstName": "Suynil",
"lastName": "Seelam",
"email": "ss.seelam#gmail.com",
"reqTitle": "Java"}]success:true,total:768}
Can you please guide me how I can achive this.I have stuglling for long over this issue!
I tried a bit and getting something likethis.
private Map<String,Object> getMap(List<CandidateStatus> candidatestatus){
Map<String,Object> modelMap = new HashMap<String,Object>(3);
Map<String,Object> candDetails = new HashMap<String,Object>(7);
Iterator<CandidateStatus> iterator=candidatestatus.iterator();
CandidateStatus astring = new CandidateStatus();
String Client;
String Fname;
String Lname;
String Email;
String Phone;
String Status;
String Require;
while(iterator.hasNext())
{
astring = iterator.next();
/*System.out.println(astring.getCandidate().getFirstName());
System.out.println(astring.getCandidate().getLastName());
System.out.println(astring.getCandidate().getEmail());
System.out.println(astring.getStatusTitle());
System.out.println(astring.getRequirement().getReqTitle());*/
Client = astring.getRequirement().getClient().getClientName();
Fname = astring.getCandidate().getFirstName();
Lname = astring.getCandidate().getLastName();
Email = astring.getCandidate().getEmail();
Phone = astring.getCandidate().getPhone();
Status = astring.getStatusTitle();
Require= astring.getRequirement().getReqTitle();
candDetails.put("clientName",Client);
candDetails.put("firstName",Fname);
candDetails.put("lastName",Lname);
candDetails.put("email",Email);
candDetails.put("phone",Phone);
candDetails.put("statusTitle",Status);
candDetails.put("reqTitle",Require);
//jsonMap.put("root", candDetails);
//System.out.println(jsonMap);
}
//System.out.println("----"+candDetails+"----");
modelMap.put("success", true);
modelMap.put("total",candDetails.size());
modelMap.put("data",candDetails );
return modelMap;
Now when I try to add candDetails to the modelMap I get only the LAST record.Why???
Thanks

I don't think your second example is valid JSON, at least according to json.org. An object is defined as:
an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).
That tells me that JSON has to start with a '{' and end with a '}'.

Your approach will work, if you change you work with map candDetails witch is kinda silly. In your loop you put data with same key, thats why you get data with last iterate.
I suggest you to write custom wrapper object(lets call it CandidateStatusWrapper and build there all structure you need. Then you just return list of wrapped objects.
Wrapper example:
class CandidateStatusWrapper {
String clientName;
String firstName;
public CandidateStatusWrapper(String clientName, String firstName) {
this.clientName = clientName;
this.firstName = firstName;
}
}
Change your map:
Map<String,Object> candDetails = new HashMap<String,Object>(7);
into list:
List<CandidateStatusWrapper> = new ArrayList<CandidateStatusWrapper >();
Loop in Controller:
while(iterator.hasNext())
{
astring = iterator.next();
Client = astring.getRequirement().getClient().getClientName();
Fname = astring.getCandidate().getFirstName();
CandidateStatusWrapper wrapped = new CandidateStatusWrapper(Client, Fname);
candDetails.add(wrapped);
}

Related

Android Kotlin parsing nested JSON

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.

ibm mobilefirst Adapter - convert JSONObject to POJO class

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.)

Map<String, HashSet<String>> to JSON, & Pretty Print

I'm trying to make my dataset correspond to this example:
var family = [{
"name" : "Jason",
"age" : "24",
"gender" : "male"
},
{
"name" : "Kyle",
"age" : "21",
"gender" : "male"
}];
I have a Map<String, HashSet<String>> of Names and unique alpha-numeric values correponding to specific entities to which those names could refer, let's call these entry items "IDs".
So for instance, Fyodor Mikhailovich Dostoyevsky would perhaps be related to the ID Q626, because that's a very specific reference, there aren't many widely known figures with that name. Whereas, Bush might be attached to G027, Q290, and Q118, referencing perhaps the man, the beer, and the shrub, in no particular order.
It looks like this (the real one is much bigger):
[Rao=[Q7293658, , Q7293657, Q12953055, Q3531237, Q4178159, Q1138810, Q579515, Q3365064, Q7293664, Q1133815], Hani Durzy=[], Louise=[, Q1660645, Q130413, Q3215140, Q152779, Q233203, Q7871343, Q232402, Q82547, Q286488, Q156723, Q3263649, Q456386, Q233192, Q14714149, Q12125864, Q57669, Q168667, Q141410, Q166028], Reyna=[Q7573462, Q2892895, Q363257, Q151944, Q3740321, Q2857439, Q1453358, Q7319529, Q733716, Q16151941, Q7159448, Q5484172, Q6074271, Q1753185, Q7319532, Q5171205, Q3183869, Q1818527, Q251862, Q3840414, Q5271282, Q5606181]]
Using Jackson I tried like this:
Map<String, HashSet<String>> map = q_valMap;
mapper.writeValue(new File("JSON_Output/user.json"), map);
But this seems wrong, as my output was all jumbled together, i.e.
{"Rao":["Q7293658","","Q7293657","Q12953055","Q3531237","Q4178159","Q1138810","Q579515","Q3365064","Q7293664","Q1133815"],"Hani Durzy":[""],"Louise":["","Q1660645","Q130413","Q3215140","Q152779","Q233203","Q7871343","Q232402","Q82547","Q286488","Q156723","Q3263649","Q456386","Q233192","Q14714149","Q12125864","Q57669","Q168667","Q141410","Q166028"],"Reyna":["Q7573462","Q2892895","Q363257","Q151944","Q3740321","Q2857439","Q1453358","Q7319529","Q733716","Q16151941","Q7159448","Q5484172","Q6074271","Q1753185","Q7319532","Q5171205","Q3183869","Q1818527","Q251862","Q3840414","Q5271282","Q5606181"]}
Do I just have to populate this JSON object iteratively?
Like the example up top, I think it should look something like this, though what follows is only a pseudocodish characterization, which is to say, not exactly this but something similar:
{
key: "Rao"
value: ["Q7293658","","Q7293657","Q12953055","Q3531237","Q4178159","Q1138810","Q579515","Q3365064","Q7293664","Q1133815"]
key: "Hani Durzy"
value: [""]
key: "Louise"
value: ["","Q1660645","Q130413","Q3215140","Q152779","Q233203","Q7871343","Q232402","Q82547","Q286488","Q156723","Q3263649","Q456386","Q233192","Q14714149","Q12125864","Q57669","Q168667","Q141410","Q166028"]
key: "Reyna"
value: ["Q7573462","Q2892895","Q363257","Q151944","Q3740321","Q2857439","Q1453358","Q7319529","Q733716","Q16151941","Q7159448","Q5484172","Q6074271","Q1753185","Q7319532","Q5171205","Q3183869","Q1818527","Q251862","Q3840414","Q5271282","Q5606181"]
}
is that not right?
UPDATE
public class JsonMapFileExample
{
public static void map(Map<String, HashSet<String>> q_valMap )
{
ObjectMapper mapper = new ObjectMapper();
ArrayNode array = mapper.createArrayNode();
for ( Entry entry: q_valMap.entrySet() )
{
ObjectNode node = mapper.createObjectNode()
.put("name", entry.getKey())
.put("ids", entry.getValue());
array.add(node);
}
mapper.writeValue("/home/matthias/Workbench/SUTD/nytimes_corpus/wdtk-parent/wdtk-examples/JSON_Output/user.json", array);
}
}
class MyEntity
{
private String name;
Set<String> value; // use names that you want in the result JSON
//constructors
public MyEntity()
{
}
public MyEntity(String name)
{
this.name = name;
}
//getters
public String getName()
{
return this.name;
}
public Set<String> getValue()
{
return this.value;
}
//setters
public void setName(String name)
{
this.name = name;
}
public void setValue(Set<String> value)
{
this.value = value;
}
}
You could manually set the key names, something like:
ArrayNode array = mapper.createArrayNode();
for (Entry entry: yourMap.entries()) {
ObjectNode node = mapper.createObjectNode()
.put("name", entry.key())
.putPOJO("ids", entry.value());
array.add(node);
}
mapper.writeValue(file, array);
Alternatively, you could create a class for your data
class MyEntity {
String name;
Set<String> ids; // use names that you want in the JSON result
// getters, setters if necessary
}
Transform your data map into a list of MyEntity, then use Jackson ObjectMapper to create JSON like mapper.writeValue(file, listOfMyEntities), the output would be like
[
{
"name": "some name here",
"ids": ["id1", "id2", ...]
}
// more elements here
]
how about this:
String name_list_file = "/home/matthias/Workbench/SUTD/nytimes_corpus/NYTimesCorpus/2005/01/02/test/people_test.txt";
String single_name;
try (
// read in the original file, list of names, w/e
InputStream stream_for_name_list_file = new FileInputStream( name_list_file );
InputStreamReader stream_reader = new InputStreamReader( stream_for_name_list_file , Charset.forName("UTF-8"));
BufferedReader line_reader = new BufferedReader( stream_reader );
)
{
while (( single_name = line_reader.readLine() ) != null)
{
//replace this by a URL encoder
//String associated_alias = single_name.replace(' ', '+');
String associated_alias = URLEncoder.encode( single_name , "UTF-8");
String platonic_key = single_name;
System.out.println("now processing: " + platonic_key);
Wikidata_Q_Reader.getQ( platonic_key, associated_alias );
}
}
//print the struc
Wikidata_Q_Reader.print_data();
}

how to call web api in controller and return into view MVC4

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);
}

Array retrieval from JSON file

I have an array in JSON file which look like this
{ "fields": [
{
"name": "order_id",
"type": "INTEGER",
"position": 0
},
{
"name": "district_id",
"type": "INTEGER",
"position": 1
}]
}
I'm using a TREE MODEL in retrieving the contents of the array "fields" and my code looks like this ..
public static void main(String[] args) throws JsonParseException, IOException {
File jsonFile = new File("metadata.json");
String theJsonString = jsonFile.toString();
String name = null;
String type =null;
int position = 0;
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
JsonNode rootNode = mapper.readTree(theJsonString);
JsonNode fields = rootNode.get("fields");
if (fields != null) {
for (int i = 0; i < fields.size(); i ++) {
if(fields.has("name"))
name = fields.get("name").getTextValue();
if(fields.has("type"))
type = fields.get("type").getTextValue();
if(fields.has("position"))
position = fields.get("position").getIntValue();
System.out.println(name);
}
}
}
I get the following error during the run time ::
Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('/' (code 47)): maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)
at [Source: java.io.StringReader#3eed2cab; line: 1, column: 2]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:1432)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportError(JsonParserMinimalBase.java:385)
at org.codehaus.jackson.impl.JsonParserMinimalBase._reportUnexpectedChar(JsonParserMinimalBase.java:306)
at org.codehaus.jackson.impl.ReaderBasedParser._skipComment(ReaderBasedParser.java:1498)
at org.codehaus.jackson.impl.ReaderBasedParser._skipWSOrEnd(ReaderBasedParser.java:1474)
at org.codehaus.jackson.impl.ReaderBasedParser.nextToken(ReaderBasedParser.java:362)
at org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2761)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2709)
at org.codehaus.jackson.map.ObjectMapper.readTree(ObjectMapper.java:1533)
at metadata.JSONParser.main(JSONParser.java:32)
I have just started working with JSON and hence unable to find a solution. Could anybody help me resolve this?
If you want the contents of the file metadata.json then calling toString on the file will not give you that. Instead it will give you a string which holds the path to the filename.
Instead create a FileInputStream from the File like so:
FileInputStream fis = new FileInputStream(jsonFile);
The you can use it with the mapper
JsonNode rootNode = mapper.readTree(fis);
You might also want to call fields.get(i) when you are iterating through the array to access each JsonNode contained in the array.
I have the same problem and I fixed the problem finally by this code to get the JsonParser object.
FileInputStream fis = new FileInputStream(path);
JsonParser jp = new JsonFactory().createParser(fis);
I had the same problem few days ago. My JSON have the next syntax:
{ "boxes": [
{
"name": "redBox.png",
"version": 15
},
{
"name": "blueBox.png",
"version": 9
}
]
}
I had to create method which return me POJO classes with box versions. My solution is follow:
private static List<DataVersion> receiveDataVersions() throws IOException
{
String path = System.getProperty( "user.dir" ) + File.separator +
"versions.json";
List<DataVersion> versions = new ArrayList<>();
JsonNode folder = null;
try( InputStream stream = new FileInputStream( path ) )
{
folder = new ObjectMapper().readTree( stream );
}
JsonNode boxes = folder.get( "inst" );
boxes.forEach( version -> versions.add( new DataVersion(
version.get( "name" ).getTextValue(),
version.get( "version" ).getIntValue() ) ) );
return versions;
}
POJO is as follows:
public class DataVersion
{
private String name;
private int version;
public DataVersion() {
}
public DataVersion(String name, int version) {
this.name = name;
this.version = version;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getVersion() {
return version;
}
public void setVersion(int version){
this.version=version;
}
#Override
public String toString()
{
return "DataVersion [" + "name='" + name + '\'' + ", version=" +
version + ']';
}
}
try this in your code
jsonFactory.enable(JsonParser.Feature.ALLOW_COMMENTS);