I am developing an wcf-webservice. The consumer is able to choose between an atom-response and a json-response.
My OperationContract looks like this:
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "json/json")]
Result GetData();
The Result-Type contains some strings and an array of entries.
[DataContract]
public class Result
{
[DataMember]
public string baseUrl;
[DataMember]
public string url;
[DataMember]
public string title;
[DataMember]
public int totalResults;
[DataMember]
public JsonEntries[] resources;
}
I marked the JsonEntries also as DataContract:
[DataContract]
public class JsonEntries
{
[DataMember]
public string updated;
[DataMember]
public string key;
[DataMember]
public string title;
[DataMember]
public Salary salarie;
}
However, when i am trying to run this i get the error, that the metadata could not be called. When I am deleting the [DataMember] in front of the array, i get no error, but my response doesnt contain the array.
I've seen it work like this on various exmaples. So what am i doing wrong?
thanks in advance.
robidd
Should work, here is my code sample
DataContracts
[DataContract]
public class Result
{
[DataMember]
public int totalResults;
[DataMember]
public JsonEntries[] resources;
}
[DataContract]
public class JsonEntries
{
[DataMember]
public string title;
}
OperationContract
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "getdata")]
Result GetData();
public Result GetData()
{
var jsonEntries = new List<JsonEntries>
{
new JsonEntries {title = "1"},
new JsonEntries {title = "2"},
new JsonEntries {title = "3"}
}.ToArray();
return new Result
{
resources = jsonEntries,
totalResults = 1
};
}
my get call
private Bag<T> GetData<T>(string uri)
{
try
{
var request = (HttpWebRequest) WebRequest.Create(uri);
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
request.Headers[HttpRequestHeader.Authorization] = _authorizationData;
var response = (HttpWebResponse) request.GetResponse();
Stream stream = response.GetResponseStream();
var localStream = new MemoryStream();
CopyStream(stream, localStream);
stream.Close();
var result = JsonContractExtensions.Create<T>(localStream);
return new Bag<T>(result);
}
catch (WebException ex)
{
_log.Debug(ex);
return Bag<T>.Empty;
}
catch (Exception ex)
{
_log.Debug(ex);
return Bag<T>.Empty;
}
}
Related
What i'm trying to achieve here is to get a custom response from the RequestMapping, below is the structure of the json which I'm trying to get in case of an array of objects:
{
"error": false,
"message": "the message",
"data": [{},{},...]
}
and the below in case of object
{
"error": false,
"message": "the message",
"data": {}
}
The code is working fine but the problem is "data" will not always has an array, it may store an object, so what I tried is to create a custom POJO class which contains my custom response and when I want to annotate two attributes with same name i'm getting the below error
Could not find acceptable representation
And what if I create another class which will contain the same attributes but with an JsonObject not with array, is there any better way to achieve this ?
Below are my classes :
#JsonInclude(Include.NON_NULL)
public class JsonResponseObject<T> implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private boolean error;
private String message ;
#JsonProperty(value="data")
private ArrayList<T> array;
#JsonProperty(value="data")
private Object object ;
public JsonResponseObject() {
}
public boolean isError() {
return error;
}
public void setError(boolean error) {
this.error = error;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public ArrayList<T> getArray() {
return array;
}
public void setArray(ArrayList<T> array) {
this.array = array;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
}
UserJsonController.java :
#RestController()
#RequestMapping(value = "/json")
public class UserJsonController {
#Autowired
private UserRepository userDAO;
#RequestMapping(value = "/users", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getUsers() {
ArrayList<Users> entityList = (ArrayList<Users>) userDAO.findAll();
JsonResponseObject<Users> jsonResponse = new JsonResponseObject<Users>();
jsonResponse.setError(false);
jsonResponse.setMessage("test");
jsonResponse.setArray(entityList);
return new ResponseEntity<>(jsonResponse, HttpStatus.OK);
}
#RequestMapping(value = "/users/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getUserByID(#PathVariable int id) {
JsonResponseObject<Users> jsonResponse = new JsonResponseObject<Users>();
jsonResponse.setError(false);
jsonResponse.setMessage("test");
jsonResponse.setObject(userDAO.findById(id).get());
return new ResponseEntity<>(jsonResponse, HttpStatus.OK);
}}
One of my api response is as below -
{
"statusCode": 422,
"error": "Unprocessable Entity",
"message": "Bad data received",
"err_data": {
"email": {
"location": "body",
"param": "email",
"value": false,
"msg": "Please provide valid e-mail address"
}
}
}
So, in below response.asString() represents above response body.
ApiResponse response = new Gson().fromJson(response.asString(), ApiResponse.class);
ApiResponse.class is my model which is as below:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({ "statusCode", "message" })
public class ApiResponse implements Serializable {
private static final long serialVersionUID = 1L;
#JsonProperty("message")
private String message;
#JsonProperty("statusCode")
private int statusCode;
#JsonProperty("err_data")
private List<String> errData = new ArrayList<>();
#JsonProperty("email")
private List<String> email = new ArrayList<>();
#JsonProperty("msg")
private String msg;
/**
* No args constructor for use in serialization
*/
public ApiResponse() {
}
/**
* #param message
*/
public ApiResponse(int statusCode, String message, List<String> errData, List<String> email, String msg) {
this.message = message;
this.statusCode = statusCode;
this.errData = errData;
this.email = email;
this.msg = msg;
}
#JsonProperty("statusCode")
public int getStatusCode() {
return statusCode;
}
#JsonProperty("statusCode")
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
#JsonProperty("message")
public String getMessage() {
return message;
}
#JsonProperty("message")
public void setMessage(String message) {
this.message = message;
}
#JsonProperty("err_data")
public List<String> getErrData() {
return errData;
}
#JsonProperty("err_data")
public void setErrData(List<String> errData) {
this.errData = errData;
}
#JsonProperty("email")
public List<String> getEmail() {
return email;
}
#JsonProperty("email")
public void setEmail(List<String> email) {
this.email = email;
}
#JsonProperty("msg")
public String getMsg() {
return msg;
}
#JsonProperty("msg")
public void setMsg(String msg) {
this.msg = msg;
}
}
When I am trying to get msg under "email":{}, it is returning null.
ApiResponse apiResponse = new Gson().fromJson(response.asString(), ApiResponse.class);
// this prints correct value
System.out.println(apiResponse.getMessage());
// this prints correct value
System.out.println(apiResponse.getStatusCode());
// this prints empty string array => []
System.out.println(apiResponse.getErrData());
// this also prints empty string array => []
System.out.println(apiResponse.getEmail());
// this prints null
System.out.println(apiResponse.getMsg());
I am new to fasterxml.jackson lib and not sure what I am missing.
To get msg value, what changes I'll have to do in model class above. Thank you very much in advance.
This is where your code is incorrect :
#JsonProperty("err_data")
private List<String> errData = new ArrayList<>();
#JsonProperty("email")
private List<String> email = new ArrayList<>();
Both email and errData is not a List, they are a separate Object. Just like the ApiResponse.java, you need to create POJO for both objects. For example :
public class Email {
private String location;
private String param;
private String value;
private String msg;
// define getter and setter
}
and
public class ErrData {
private Email email;
// define getter and setter
}
Then use the new class as the object type.
#JsonProperty("err_data")
private ErrData errData;
// email is already inside ErrData, you don't need to define them here
Finally to access your msg :
errData.getEmail().getMsg();
Hope this is clear enough. Good luck!
how to post call SaveCorporateProfile function by passing json
[DataContract]
public class myclass
{
public string CompanyCode { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
[ServiceContract]
public interface ICustProfileService
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/SaveCorporateProfile?dt={dt}")]
string SaveCorporateProfile(myclass dt);
}
public string SaveCorporateProfile(myclass dt)
{
return "success";
}
You can try this;
Firstly, you should edit your myclass like this;
[DataContract]
public class myclass
{
[DataMember]
public string CompanyCode { get; set; }
[DataMember]
public string Username { get; set; }
[DataMember]
public string Password { get; set; }
}
then your interface like this;
[ServiceContract]
public interface ICustProfileService
{
[OperationContract]
string SaveCorporateProfile(myclass dt);
}
And you implement your .svc file for using this interface
public class CustProfileService: ICustProfileService
{
[WebInvoke(Method = "POST",UriTemplate = "/SaveCorporateProfile?dt={dt}"
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
public string SaveCorporateProfile(myclass dt)
{
return "success";
}
}
I'm trying to DeSerialize data in json array using wcf service in the project.
The data is fetched and can be noticed in the debugging but i'm unable to deserialize, or something else that I'm mistaken. Below is the code that I've tried to deserialize.
Note:- I've separately run the wcf application and its returning json array in correct format with the actual result.
HotelServiceClient.cs
public class HotelServiceClient
{
private string BASE_URL = "http://localhost:50540/ServiceHotel.svc/";
public List<HotelInfo> findall()
{
try
{
var webClient = new WebClient();
var json = webClient.DownloadString(BASE_URL + "findall");
var javaScriptJson = new JavaScriptSerializer();
return javaScriptJson.Deserialize<List<HotelInfo>>(json);
}
catch
{
return null;
}
}
HotelInfo.cs
public class HotelInfo
{
private int _hotelid;
private string _hotelname;
private string _hoteldesc;
private string _hotelprice;
private byte[] _hotelpicture;
[Key]
[Display(Name = "Id")]
public int Hotelid
{
get
{
return _hotelid;
}
set
{
_hotelid = value;
}
}
[Display(Name = "Name")]
public string Hotelname
{
get
{
return _hotelname;
}
set
{
_hotelname = value;
}
}
[Display(Name = "description")]
public string Hoteldesc
{
get
{
return _hoteldesc;
}
set
{
_hoteldesc = value;
}
}
[Display(Name = "price")]
public string Hotelprice
{
get
{
return _hotelprice;
}
set
{
_hotelprice = value;
}
}
[Display(Name = "picture")]
public byte[] Hotelpicture
{
get
{
return _hotelpicture;
}
set
{
_hotelpicture = value;
}
}
}
WebService
Hotel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CRUDwithHotels
{
public class Hotel
{
public int Id { get; set; }
public string Name { get; set; }
public string description { get; set; }
public string price { get; set; }
public byte[] picture { get; set; }
}
}
IServiceHotel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace CRUDwithHotels
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IServiceHotel" in both code and config file together.
[ServiceContract]
public interface IServiceHotel
{
[OperationContract]
[WebInvoke(Method ="GET", UriTemplate ="findall", ResponseFormat =WebMessageFormat.Json)]
List<Hotel> findall();
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "find/{id}", ResponseFormat = WebMessageFormat.Json)]
Hotel find(string id);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "create", ResponseFormat = WebMessageFormat.Json, RequestFormat =WebMessageFormat.Json)]
bool create(Hotel hotel);
[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "edit", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
bool edit(Hotel hotel);
[OperationContract]
[WebInvoke(Method = "DELETE", UriTemplate = "delete", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
bool delete(Hotel hotel);
}
}
ServiceHotel.svc.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace CRUDwithHotels
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ServiceHotel" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select ServiceHotel.svc or ServiceHotel.svc.cs at the Solution Explorer and start debugging.
public class ServiceHotel : IServiceHotel
{
public bool create(Hotel hotel)
{
using (ModelMyDemo hie = new ModelMyDemo())
{
try
{
HotelInfoEntities info = new HotelInfoEntities();
info.Hotelname = hotel.Name;
info.Hoteldesc = hotel.description;
info.Hotelprice = hotel.price;
info.Hotelpicture = hotel.picture;
hie.HotelInfoEntities.Add(info);
hie.SaveChanges();
return true;
}
catch
{
return false;
}
};
}
public bool delete(Hotel hotel)
{
using (ModelMyDemo hie = new ModelMyDemo())
{
try
{
int id = Convert.ToInt16(hotel.Id);
HotelInfoEntities info = hie.HotelInfoEntities.Single(p => p.Hotelid == id);
hie.HotelInfoEntities.Remove(info);
hie.SaveChanges();
return true;
}
catch
{
return false;
}
};
}
public bool edit(Hotel hotel)
{
using (ModelMyDemo hie = new ModelMyDemo())
{
try
{
int id = Convert.ToInt16(hotel.Id);
HotelInfoEntities info = hie.HotelInfoEntities.Single(p => p.Hotelid == id);
info.Hotelname = hotel.Name;
info.Hoteldesc = hotel.description;
info.Hotelprice = hotel.price;
info.Hotelpicture = hotel.picture;
hie.SaveChanges();
return true;
}
catch
{
return false;
}
};
}
public Hotel find(string id)
{
int hid = Convert.ToInt16(id);
using (ModelMyDemo hie = new ModelMyDemo())
{
return hie.HotelInfoEntities.Where(pe => pe.Hotelid == hid).Select(pe => new Hotel
{
Id = pe.Hotelid,
Name = pe.Hotelname,
description = pe.Hoteldesc,
price = pe.Hotelprice,
picture = pe.Hotelpicture
}).First();
};
}
public List<Hotel> findall()
{
//var imagesrc = string.Format("data:image/jpeg;base64,{0}", base64);
using (ModelMyDemo hie = new ModelMyDemo())
{
return hie.HotelInfoEntities.Select(pe => new Hotel
{
Id = pe.Hotelid,
Name = pe.Hotelname,
description = pe.Hoteldesc,
price = pe.Hotelprice,
picture = pe.Hotelpicture
// picture = pe.Hotelpicture
}).ToList();
};
}
}
}
at first we need an object in order to deserilize the the result in it.
public class RootObject
{
public int Id { get; set; }
public string Name { get; set; }
public string description { get; set; }
public List<byte> picture { get; set; }
}
now all we need is to deserilize the json result in to the object. but your json is twice serilized so you need to deserilized it twice like this:
public RootObject findall()
{
try
{
var webClient = new WebClient();
var json = webClient.DownloadString(BASE_URL + "findall");
return JsonConvert.DeserializeObject<RootObject[]>(json);
}
catch
{
return null;
}
}
I have a REST service defined in Spring as follows:
#RequestMapping(value = "/create", method = RequestMethod.POST)
#ResponseBody
public ResponseEntity<String> addArticle(#RequestBody Article article){
try{
articleService.addArticle(article.getTitle(),
article.getContent(),
article.getTags(),
article.getPublishStatus(),
article.getCompanyId(),
article.getCategory());
return new ResponseEntity<String>(HttpStatus.OK);
} catch (Exception e){
e.printStackTrace();
return new ResponseEntity<String>(e.getMessage(), HttpStatus.OK);
}
}
And my article is defined as follows:
public class Article {
private int id;
private String title;
private String content;
private String smsContent;
public String getSmsContent()
{
return smsContent;
}
public void setSmsContent(String smsContent)
{
this.smsContent = smsContent;
}
private String[] tags;
private int companyId;
private String category;
public String getCategory(){
return category;
}
public void setCategory(String category){
this.category = category;
}
private byte publishStatus;
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title = title;
}
public String getContent(){
return content;
}
public void setContent(String content){
this.content = content;
}
public String[] getTags(){
return tags;
}
public void setTags(String[] tags){
this.tags = tags;
}
public int getCompanyId(){
return companyId;
}
public void setCompanyId(int companyId){
this.companyId = companyId;
}
public byte getPublishStatus(){
return publishStatus;
}
public void setPublishStatus(byte publishStatus){
this.publishStatus = publishStatus;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
}
How do I call this service using Angular? I tried following code:
function createArticle(name, companyId, title, content, tags, category) {
var request = $http({
method : 'POST',
url : '/inbound/api/article/create.json',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
transformRequest : function(obj) {
var str = [];
for ( var p in obj)
str.push(encodeURIComponent(p) + "="
+ encodeURIComponent(obj[p]));
return str.join("&");
},
data : {
title : title,
content : content,
tags : tags,
companyId : companyId,
category: category
}
});
I am getting error 415 (Unsupported Media Type). Any ideas?
Since you're working with JSON, you need to set your form and handler accordingly.
REST handler
#RequestMapping(value = "/create", method = RequestMethod.POST, consumes = "application/json")
Angular
headers : {
'Content-Type' : 'application/json'
},
First
you have:
#RequestMapping(value = "/create", method = RequestMethod.POST)
just /create
Second
You have:
url : '/inbound/api/article/create.json',
Proceed to remove the .json that's the problem
Third
Be sure to indicate for the ajax event, the data you are sending is in JSON