DataContract and Serializable in WCF Service - json

I try to write a demo with WCF (REST) Service, and I use LinqToSQL as my db operator.
When I try to pub [DataContract] or [Serializable] on top of my domain object, it cannot be serialized to JSON. I only can get a pair of '{}' in my browser. After removing [DataContract] or [Serializable] attribute, it become normal again.
[DataContract]
public partial class MyDoc{ } // a Linq To SQL domain class
get method:
[WebGet(UriTemplate = "GetMyDoc/{docID}",ResponseFormat=WebMessageFormat.Json)]
[ServiceKnownType(typeof(MyDoc))]
public WcfRESTfulTest.Db.MyDoc GetMyDoc(string docID)
{
WcfRESTfulTest.Db.DbDataContext db = new DbDataContext();
var query = db.MyDocs.Where(d => d.DocID.Equals(Int32.Parse(docID)));
return query.FirstOrDefault();
}

If you don't use the [DataContract] attribute, all public properties will be serialized. If you do use it, you'll have to opt-in the properties you want to serialize, using the [DataMember] attribute.

Related

Angular casting http get response but not nested property

I am returning a list of products of type ListProd in my Spring Boot controller, and such object has a nested property of type List<Product> ... something like this:
public class Product implements Serializable {
int codProdct;
String dsc;
public Product(){};
// plus getters and setters (omitted for simplicity)
}
public class ListProd implements Serializable {
int codList;
List<Product> products;
public ListProd(){};
// also here getters and setters
}
and in my angular project I have the next analogoust entities:
export class Product {
public codProduct:number;
public dsc:string;
constructor(){
codProduct=null; //just for completness
dsc='';
}
}
export class ListProd {
public codList:number;
public products:Product[];
constructor(){
this.codList=null; //just for completness
this.products=null;
}
}
I'm sending a ListProd object through my Spring controller and Angular gets such an object correctly and assigns the type also correctly:
return this.http.get<ListProd>(this.apiUrl + "/getListProds", httpOptions);
but ... it is only casting correctly the parent object, when I check the type of the 'products' object (which is recived correctly, only untyped) y get type: Object
I tried to make it a Products[] in my ListProd class in java, but i get the same result. I don't know much about the 'magic' Angular does to assign those types properly, am I missing something important here? Is there a chance to force the casting on the Angular side?
Thanks in advance.
Well, if ListProd is supposed to hold array of Product[] there is a typo here.
public products:Product[];
Not knowing full extent why you use class over an interface I would advise you also to go over this. Maybe there is a reason but for being able to strong type simple interface would be better. https://www.javatpoint.com/typescript-class-vs-interface

How to make Enunciate show my data type as structured JSON (instead of as "custom")?

I have this simple service which echoes an ID parameter wrapped in a JSON object:
#Path("job")
public class JobResource {
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{id}")
public Job readById(#PathParam("id") long id) {
Job j = new Job();
j.id = id;
return j;
}
}
The return value's Job class is declared as:
public class Job {
public long id;
}
The documentation generated with Enunciate shows the service's data type as "custom". Is it possible to have Enunciate spit out a more detailed explanation of the return type, for example a JSON representation?
If you change the return type to javax.ws.rs.core.Response the documentation should then show the data type as JSON.
You would need to slightly modify your method as:
...
return Response.status(Status.OK).entity(j).build();
Add annotation to the Job class
#javax.xml.bind.annotation.XmlRootElement
Without this annotation the enunciate will display the DTO as "custom" or "file"
I got exactly the same problem with a simple REST Jersey webservice.
Here are the annotations of My returned object (no more):
#XmlRootElement(name = "OReponseInitialiser")
#XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
#XmlType (name="OReponseInitialiser")
public class OReponseInitialiser
And the webservice declaration:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path ("initialiser")
public OReponseInitialiser initialiser(#Context HttpServletRequest pRequete, ...) throws OException
I build the documentation with the ant task
<enunciate
basedir="${projet.repertoire}/src"
buildDir="${enunciate.working.dir}"
javacSourceVersion="1.8"
javacTargetVersion="1.8"
configFile="${projet.repertoire}/build_enunciate.xml"
>
<include name="**/*.java"/>
<classpath refid="compile.classpath"/>
<export artifactId="docs" destination="${docs.dir}"/>
</enunciate>

Automapper map to existing object stack overflow exception

i'm coding a restService who can update some datas in a database via Nhibernate.
The service receive DTO objects from a client.
I'm using Automapper to map my Dto to NhibernateObject.
The problem is my DTO class reference itself. here an example :
public class UserDto
{
public String Name{get;set;}
public string Lastname{get;set;}
public UserDto UserOwner{get;set;}
}
here's my BusinessClass
public class User
{
public String Name{get;set;}
public string Lastname{get;set;}
public String Adress{get;set;}
public User UserOwner{get;set;}
}
Sometimes User object and UserOwner properties references the same object.
So when i do that
User usr = Automapper.Mapper.Map<UserDto,User>(myUserDtoObject); // this works fine
but when i do
Automapper.Mapper.Map(myUserdtoObject,MyUserNhibernateObject); // i've got a stackoverflowexception
I can use the first option but if i do that, when my new UserEntity returned by Map function is created the value of "Adress" properties is not set (UserDto does not contains it).
You need to use MaxDepth - AutoMapper doesn't know how far to go down your rabbit hole.
ForMember(dest => dest.UserOwner, opt => opt.MaxDepth(1))
This is important for NHibernate, which uses proxy objects to load indefinitely. The other option is to ignore the UserOwner member, but that's likely not your intent here.

spring rest #requestbody get child object

I has a problem:There will be three child class Student,Teacher,Parent.
public class Person implements Serializable{
private String name;
private String address;}
Student:
public class Student extends Person {
private String cardNo;
}
spring rest :
#RequestMapping(method = RequestMethod.POST, value = "/create")
#ResponseBody
public CemeteryRestResponse<Boolean> create(
#RequestBody Person person) throws Exception {.....}
I want to use the one rest method to create these three role.
but in client post Student as JSON it throws a Exception :
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "cardNo"
thanks in advance!
The Jackson library supports polymorphic type handling which is what it appears you are after. The specific annotation you should be looking for is the #JsonTypeInfo annotation, and you should apply it to the base class (the Person class).
This feature was added in version 1.5.

Jackson deserialization when POJO does not match JSON structure

I have some json :
{
key: "CORE-19",
fields: { summary: "iblah" }
}
I want to pack it into a POJO that looks more like:
#JsonIgnoreProperties(ignoreUnknown=true)
public class JiraIssue
{
private String mKey;
private String mSummary;
public String getKey(){ return(mKey);}
public void setKey(String inKey){mKey = inKey;}
public String getSummary(){return(mSummary);}
public void setSummary(String summary){ mSummary = summary; }
}
So basically I don't want to create a 'Fields' object as it is a bit superfluous for my needs. However I really can't see any way in Jackson to tell it that the 'summary' property actually comes from the 'fields' property. Is this possible?
Serialization of this class is not a concern, it will only ever be used for Deserialization. I have no control over the JSON format as it is coming from an external source (and the above is just a snippet). Also I'm actually using Jackson with Jersey.
Thanks!
There is actually an open issue for this kind of structural change. There is no way as of now to do that easily with annotation only without modifying your class. What you could do instead is handle the "fields" property as a "false" property, by adding the following method:
public void setFields(Map<String, String> fields) {
setSummary(fields.get("summary"));
}
This way you "unwrap" the property yourself.
Try:
#JsonProperty("fields.summary")
private String mSummary;