GSON not reading values correctly - json

I'm trying to read this JSON:
And I can't seem to get it to work with GSON. I've used GSON successfully in the same project so I know how it works but I can't seem to get this JSON to work as intended. First in the class is rows, which is just an array of another class. The other class has three variables, a string named "code", a string named "name", and a array of another class called "statuses". However, I don't know how to put variables in this other class. It looks like an array but it's not. I cannot name a variable "0" in Java, so I looked that up (tried fixing it with Maps) but that did not work. How would you do this? It's weird because "statuses" always contains just that one entry, named '0', and the text is either "primary" or "secondary". Any help is appreciated.
I actually found this:
Still not really sure how to go about this.

Your Pojo design shoild be like this :-
public class ResultOutPut {
private List<Rows> rows;
// getters and setters
}
public class Rows {
private String code;
private String name;
private List<String> statuses;
// getters and setters
}

Related

How to select class for collection member in fasterxml JSON conversion

In my REST application I am using fasterxml to serialize and deserialize POJOs to JSON. I run into problems with collections such as List in a case like this.
public class JsonRequest {
public int anumber;
public String astring;
public List<XyzClass> data;
}
The properties anumber and astring convert back and forth just fine without any annotations. For **data*, although the compiler can see that the List elements are (should be) XyzClass that information is not available to the jackson framework, so it doesn't know what class to use when deserializing the elements.
For some reason I can't make sense of the documentation as to which annotation to use to fix this. The #JsonDeserialize annotation doesn't help this. Can anyone point me in the right direction?
After some research I finally found out how to make this work.
public class JsonRequest {
public int anumber;
public String astring;
#JsonDeserialize(contentAs = XyzClass.class) // <-- Added
public List<XyzClass> data;
}
To answer the questions in comments above, the code for XyzClass is just a trivial POJO like:
public class XyzClass {
public String name;
public int age;
}
What was tripping me up is that I was looking for an annotation to the effect of #JsonDeserializeContentAs(class = XyzClass.class) which doesn't exist because I missed the fact that #JsonDeserilize had a contentAs option.
Hopefully this posting will save someone else the same trouble.

Does the business logic for deserializing a JsonPayload have to match?

I am currently attempting to deserialize a Json Payload that has been fired from a webhook URL on an MVC application, but I do not know if the business logic provided has to match exactly to prevent any null values.
Basically the Json Payload contains way to much useless information that I do not what to display. This is a brief preview of what the Payload looks like:
"webhookEvent":"jira:issue_updated",
"user":{
"self":"http://gtlserver1:8080/rest/api/2/user?username=codonoghue",
"name":"codonoghue",
"issue":{
"id":"41948",
"self":"http://gtlserver1:8080/rest/api/2/issue/41948",
"key":"OP-155",
"fields":{
"summary":"Test cc recipient",
"progress":{
"progress":0,
"total":0}, ....
I only want to display information about the issue and the other information is just white noise to me and don't want to use it. Now do I have to create classes only for the issue details etc like this:
Public Class jiraIssue
Public Property id As String
Public Property key As String
Public Property fields As jiraFields
End Class
Or do I have to make sure to provide sufficient business logic about the User class just to make sure that it will be received correctly? I also know that using Json2csharp.com the classes that can be made are user, issue, fields, progress as well as the overall RootObject, so I also want to know is do these classes need to contain the exact same matching variables as the JsonPayload, e.g. I don't want progress to have the variable total.
When using Json2csharp that in every class they contain an ID variable with the property as string and I would like to know if this is needed in the classes to be able to display the information or can I not use it as it is also irrelevant.
The main thing that I want to deserialize is the RootObject, which contains a webhookEvent (string) an issue (which links to issue class, which links to fields class which links to all relevant information), comment which links to a comment class. I want to deserialize this so would this be correct?
Public Class Rootobject
Public Property webhookEvent As String
Public Property issue As Issue
Public Property comment As Comment2
Public Property timestamp As Long
End Class
Public Class Issue
Public Property key As String
Public Property fields As Fields
End Class
Public Class Fields
Public Property issueType as IssueType
Public Property summary As String
Public Property summary As String
End Class
Dim Issue As RootObject = New System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(Of RootObject)(json)
For Each item As var In Issue.issue
Console.WriteLine("WebhookEvent: {0}, issue: {1}", item.WebhookEvent, item.issue)
Next
Update
It seems that the problems that I was having was due to the JsonPayload itself, the business logic did not affect. There were issues with the incompatible characters, some fields were null and could not be and a few others as well.
I have correctly got my Json payload correctly read in and the Json Payload information does not have to correctly match up with the classes that you create. You only have to create classes and variables for the information that you need from the Json Payload. For example if you did not want the information on comments do not create a comment class.
Public Class Rootobject
Public Property webhookEvent As String
Public Property issue As Issue
' Public Property comment As Comment2
' comment out the comment class because it is not needed
Public Property timestamp As Long
End Class

Factory to return array of IItem from single object

This is a simplified version of the problem i am solving but conceptually equivalent.
This project is using castle windsor and I am trying to keep all factories in the container.
I have a single object that represents data parsed from a text file. After parsing this file I need to write a new text file with 2 line based on data in the original object.
lets say the text file is
Some Person, Work Phone, Mobil Phone
this gets parsed into
public class Person
{
public string Name{get;set;}
public stirng WorkPhone {get;set;}
public stirng MobilPhone {get;set;}
}
Now this is a simplified example so keep that in mind please. The next step is to creat new object instances that represent each line we will write to the text file
public interface IFileEntry
{
string Name{get;set;}
string Number{get;set;}
}
public class PersonWorkPhoneEntry : IFileEntry
{
public string Name {get;set;}
public string Number{get;set;}
public override ToString(){....}
}
public class PersonMobilPhoneEntry: IFileEntry
{
public string Name{get;set;}
public string Number{get;set;}
public override ToString(){....}
}
so being that we are using Castle for this lets make a factory
public interface IFileEntryFactory
{
IFileEntry Create(string entryType, stirng Name, string Number
}
I have created my own implementation for the DefaultTypedFactoryComponentSelector and install that for this factory only.
public class FileEntryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments)
{
if (method.Name == "Create" && arguments.length == 3)
{
return (string)arguments[0];
}
return base.GetComponentName(method, arguments);
}
}
This works,
var workEntry = _factory.Create("PersonWorkPhoneEntry", person.Name, person.WorkPhone)
var mobilEntry = _factory.Create("PersonMobilPhoneEntry", person.Name, person.WorkPhone)
//then write the tostring to a text file
Sorry for the long setup but i think its needed. What I am trying to do Is
public interface IFileEntryFactory
{
IFileEntry Create(string entryType, stirng Name, string Number
IFileEntry[] Create(Person person)
}
var entries = _factory.Create(person);
foreach(var e in entries)
///write to text file.
I have been digging all over for a solution like this with no results.
What seems to be a possible solution taking the example shown here (Castle Windsor Typed Factory Facility with generics)
Im currently working on implementing something like this now, not sure if this is the right way to solve this problem.
The questions:
are there any other ways to have the factory return the array of
needed objects
what is the best practice for solving something like
this
any examples and reading for advanced factories
It is possible to make a Factory return to you an array of objects which are already registered in the container. Here is an example
container.Register(Component.For<IMyStuffProvider>().AsFactory()) // registration
public interface IStuffProvider
{
IEnumerable<IMyStuff> GetAllStuff();
void Release(IMyStuff stuff);
}
This code makes possible that every registered implementation of IMyStuff gets returned by the factory.
But I think that your problem is different : you are using the factory for the wrong purpose. TypedFactory is to get instances of objects that are already registered in the container during app start and not to manipulate files. Their purpose is to solve problems regarding dependencies.
If you are parsing a csv/txt into objects and then writing some of the rows back into another csv/txt you have to make
IFileEntryManager (with an implementation) with a methods like DeserializeFileToObjects, WriteObjectsToFile, etc.
IFileEntryManagerFactory to create and return IFileEntryManager. ( Castle typed factory here :) )
Now inject your IFileEntryManagerFactory in your ctor of the class that needs to serialize/deserialize text files and and use it to get your FileEntryManager which in turn will act upon your text files.
If you have different objects like Person, Company, Employee... etc. and you want to handle them with generic manipulator - it is ok. The best way is to implement a Generic Repository. Lets say ICsvRepository<T>. Just search for 'Generic Rpository in c#' and ignore that fact that most of the implementation examples are with EntityFramework as a persistence store. Behind the interface you can make it read/write to csv rather than to DB.
Lets generalize it. If you have to deal with resources - files, sql, blobs, tables, message bus or whatever resource persistent/non persistent which comes in or goes out of your application you have to manipulate it through an abstraction IMyResourceManager with its corresponding manipulation methods. If you have several implementations of IMyResourceManager and you want to decide during runtime which implementation you want then you have to make IMyResourceManagerFactory with a component selector or factory method and place your differentiation logic there.
That is why I think you do not need a TypedFactory for text file read/write but a pure ITextFileManipulator which you have to register in the container and get it through constructor. You may need a typed factory if you go for ICsvRepository<T> where T is your Person class. Inside the implementation of ICsvRepository<T> you will need ICsvFileManipulator.

Is #XmlElement necessary for Jaxb

My question is, whether it is necessary to add #XmlElement before each element in your pojo to be picked up by jaxb, when making a JSON response. I am using jersey-json 1.17 . The reason I ask this is because, the example given on Jersey site does not use the annotation.
I get an out put as {}, but when I add #XmlElement before the attributes, I get the expected JSON output. Am I doing something wrong, because of which my JSON string is empty ?
My code :
The vertices list is populated in the constructor.
This produces the wrong output of {}
#XmlRootElement
public class SquareModel {
List<Float> vertices = new ArrayList<Float>();
....
}
Whereas this produces the a correct JSON string :
#XmlRootElement
public class SquareModel {
#XmlElement(name="vertices")
List<Float> vertices = new ArrayList<Float>();
....
}
My resource class which returns the JSON
#GET
#Produces(MediaType.APPLICATION_JSON)
public SquareModel getJsonString() {
return new SquareModel();
}
Thanks :)
No, by default a JAXB (JSR-22#) implementation will treat all public fields and properties (get/set combinations) as mapped (not requiring the #XmlElement annotation).
http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
If you wish to annotate a field I would recommend annotating your class with #XmlAccessorType(XmlAccessType.FIELD)
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
According to this http://jersey.java.net/nonav/documentation/latest/json.html#json.jaxb.approach.section
You should have this annotation (I'm also using it in my code, even though it XML oriented, but it gives me cool JSON also)
Taking this approach will save you a lot of time, if you want to
easily produce/consume both JSON and XML data format. Because even
then you will still be able to use a unified Java model. Another
advantage is simplicity of working with such a model, as JAXB
leverages annotated POJOs and these could be handled as simple Java
beans.
A disadvantage of JAXB based approach could be if you need to work
with a very specific JSON format. Then it could be difficult to find a
proper way to get such a format produced and consumed. This is a
reason why a lot of configuration options are provided, so that you
can control how things get serialized out and deserialized back.
Following is a very simple example of how a JAXB bean could look like.
Example 5.3. Simple JAXB bean implementation
#XmlRootElement
public class MyJaxbBean {
public String name;
public int age;
public MyJaxbBean() {} // JAXB needs this
public MyJaxbBean(String name, int age) {
this.name = name;
this.age = age;
}
}

How to add extra fields to an Object during Jackson's json serialization?

I need to add new property to an object, when serializing to JSON. The value for the property is calculated on runtime and does not exist in the object. Also the same object can be used for creation of different JSON with different set ot fields (kind of having a base class with subclasses, but I don't want to create ones just for JSON generation).
What is the best way of doing that, which doesn't involve creation of custom serializer class, which will take care of serializing of whole set of object's fields? Or may be it is possible to inherit some "basic" serializer, and simply take it's output and add new field to it somehow?
I learned about mixins, and looks like it is possible to rename/hide some fields, however it seems not be possible to add an extra one.
Can you not just add a method in value class? Note that it does not have to be either public, or use getter naming convention; you could do something like:
public class MyStuff {
// ... the usual fields, getters and/or setters
#JsonProperty("sum") // or whatever name you need in JSON
private int calculateSumForJSON() {
return 42; // calculate somehow
}
}
Otherwise you could convert POJO into JSON Tree value:
JsonNode tree = mapper.valueToTree(value);
and then modify it by adding properties etc.
2021 calling...
Simplest way I found to do this is #JsonUnwrapped:
public class Envelope<T> {
#JsonUnwrapped // content's fields are promoted alongside the envelope's
public T content;
// Transmission specific fields
public String url;
public long timestamp;
}
This works (bi-directionally) so long as Envelope's fieldnames do not clash with those of content. Also has a nice feature of keeping the transmission properties at the end of the serialised JSON.
One option is to add a field for this property and set it on the object before writing to JSON. A second option, if the property can be computed from other object properties you could just add a getter for it, for example:
public String getFullName() {
return getFirstName() + " " + getLastName();
}
And even though there's no matching field Jackson will automatically call this getter while writing the JSON and it will appear as fullName in the JSON output. If that won't work a third option is to convert the object to a map and then manipulate it however you need:
ObjectMapper mapper //.....
MyObject o //.....
long specialValue //.....
Map<String, Object> map = mapper.convertValue(o, new TypeReference<Map<String, Object>>() { });
map.put("specialValue", specialValue);
You're question didn't mention unmarshalling but if you need to do that as well then the first option would work fine but the second two would need some tweaking.
And as for writing different fields of the same object it sounds like a job for #JsonView