This question already has answers here:
Serialize Java List to XML using Jackson XML mapper
(3 answers)
Closed 5 years ago.
I am learning to use Jackson to serialize XML. My class structure is as below.
class City {
#JacksonXmlProperty(localName = "CityName")
String cityName;
public City(String cityName) {
this.cityName = cityName;
}
public String getcityName() {
return cityName;
}
public void setcity(String cityName) {
this.cityName = cityName;
}
}
#JacksonXmlRootElement(localName = "Person")
class Person {
#JacksonXmlProperty(localName = "name")
private String name;
#JacksonXmlProperty(localName = "age")
private String age;
#JacksonXmlProperty(localName = "city")
private List<City> city;
public Person() { }
Person(String name, String age, List<City> city) {
this.name = name;
this.age = age;
this.city = city;
}
public String getname() {
return name;
}
public String getage() {
return age;
}
public List<City> getcity() {
return city;
}
public void setname(String name) {
this.name = name;
}
public void setage(String age) {
this.age = age;
}
public void setcity(List<City> city) {
this.city = city;
}
}
When I try to serialize a class to XML using Jackson, I get two tags for <city>
public class App
{
public static void main( String[] args )
{
try {
XmlMapper xmlMapper2 = new XmlMapper();
Person p = new Person();
City c1 = new City("abc");
City c2 = new City("def");
City c3 = new City("ghi");
List<City> cityList = new ArrayList<City>();
cityList.add(c1);
cityList.add(c2);
cityList.add(c3);
p.setname("setattr");
p.setage("55");
p.setcity(cityList);
xmlMapper2.enable(SerializationFeature.INDENT_OUTPUT);
String respPerson = xmlMapper2.writeValueAsString(p);
System.out.println(respPerson);
} catch (Exception e) {
e.printStackTrace();
}
}
This is the output that I get.
<Person><name>setattr</name><age>55</age><city><city><CityName>sfo</CityName></city><city><CityName>sjc</CityName></city><city><CityName>sea</CityName></city></city></Person>
Can you help me to understand why do I get two tags for city and how I can fix it?
I would like the output to be something like,
<Person><name>setattr</name><age>55</age><city><CityName>sfo</CityName><CityName>sjc</CityName><CityName>sea</CityName></city></Person>
You have a list of cities. Jackson is using 'city' for both the list itself and the members of the list. If you change the local name to 'cities', you might like the results better.
Unfortunately, this isn't the right answer. It appears, rather, that the right answer is provided https://stackoverflow.com/a/27144625/131433.
Related
Hello and sorry if I did not explain myself properly.
I am trying to compare if a String is within a previously created list of objects.
example:
List<People> listOfPeople = new ArrayList<>();
Person person1 = new Person("Marija" , "Zagreb");
Person person2 = new Person("Joan", "Barcelona");
Person person3 = new Person("Vinko" , "Zagreb");
listOfPeople.add(person1);
listOfPeople.add(person2);
listOfPeople.add(person3);
What I want to do is checking the city value and be able to create a message if a person appears has the same location. I can't seem to search strings of specific values within a list.
listOfPeople.contains is telling me "given object cannot contain instances of String.
Please let me know if I should extend my question.
Thanks beforehand.
From java8, you can use stream, example bellow
import java.util.ArrayList;
import java.util.List;
public class newExample {
public static void main(String[] args) {
List<People> listOfPeople = new ArrayList<People>();
People People1 = new People("Marija", "Zagreb");
People People2 = new People("Joan", "Barcelona");
People People3 = new People("Vinko", "Zagreb");
listOfPeople.add(People1);
listOfPeople.add(People2);
listOfPeople.add(People3);
String city = "Barcelona";
if (listOfPeople.stream().anyMatch(x -> x.getCity().equals(city))) {
// found
}
}
}
class People {
String name;
String city;
public People(String name, String city) {
this.name = name;
this.city = city;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
Assuming you are using Java 8 and above, you can use this:
package com.Example;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Person> listOfPeople = new ArrayList<>();
Person person1 = new Person("Marija" , "Zagreb");
Person person2 = new Person("Joan", "Barcelona");
Person person3 = new Person("Vinko" , "Zagreb");
listOfPeople.add(person1);
listOfPeople.add(person2);
listOfPeople.add(person3);
listOfPeople.stream()
.filter(p -> p.getCity().equals("Barcelona"))
.forEach(System.out::println);
}
}
class Person implements Serializable{
private static final long serialVersionUID = -414171236169806542L;
private String name;
private String city;
public Person(String name, String city) {
super();
this.name = name;
this.city = city;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
#Override
public String toString() {
return "Person [name=" + name + ", city=" + city + "]";
}
}
Output:
Person [name=Joan, city=Barcelona]
When I use #JsonUnwrapped on nested field:
public class Person{
private int id;
#JsonUnwrapped
private Father father
//getters/setters
#Data
#AllArgsConstructor
private static class Father {
private String name;
private String surname;
}
And at the same time I use the #JsonCreator:
#JsonCreator // DESERIALIZATION: JSON -> POJO
public Person(...
#JsonProperty("name") String name,
#JsonProperty("surname") String surname) {
(...)
this.father = new Father(name, surname);
with Father being nested class.
I get the error:
Father` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creat
But when I remove the #JsonUnwrapped the field gets deserialised ok but is not flatten during serialisation.
How to assure that Father field will be serialised and deserialised flatten at the same time?
EDIT:
I paste full code:
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class Person {
private int id;
private String firstName;
private String lastName;
private boolean active;
private Address address;
private String[] languages;
#JsonIgnore private boolean isTheKing;
#JsonUnwrapped // SERIALIZATIONL POJO -> JSON
private Father father;
#JsonCreator // DESERIALIZATION: JSON -> POJO
public Student(
#JsonProperty("id") int id,
#JsonProperty("firstName") String firstName,
#JsonProperty("lastName") String lastName,
#JsonProperty("active") boolean active,
#JsonProperty("address") Address address,
#JsonProperty("languages") String[] languages,
#JsonProperty("isTheKing") boolean isTheKing,
#JsonProperty("name") String name,
#JsonProperty("surname") String surname) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.active = active;
this.address = address;
this.languages = languages;
this.isTheKing = isTheKing;
this.father = new Father(name, surname);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getLanguages() {
return languages;
}
public void setLanguages(String[] languages) {
this.languages = languages;
}
public Father getFather() {
return father;
}
public void setFather(Father father) {
this.father = father;
}
#Data
#AllArgsConstructor
static class Father {
private String name;
private String surname;
}
}
the following main method fails:
ObjectMapper mapper = new ObjectMapper();
Person myStudent =
mapper.readValue(new File("src/main/resources/data/rest/studentIN.json"), Person.class);
System.out.println(myStudent);
with error:
Exception in thread "main"
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot
construct instance of com.example.demo.Person$Father
(no Creators, like default construct, exist): cannot deserialize from
Object value (no delegate- or property-based Creator)
I use lombok:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
It should work for simple POJO model. Father class should be public:
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class JsonApp {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
Person.Father father = new Person.Father();
father.setName("Wit");
father.setSurname("Pil");
Person person = new Person();
person.setId(1909);
person.setFather(father);
String json = mapper.writeValueAsString(person);
System.out.println(json);
System.out.println(mapper.readValue(json, Person.class));
}
}
class Person {
private int id;
#JsonUnwrapped
private Father father;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Father getFather() {
return father;
}
public void setFather(Father father) {
this.father = father;
}
#Override
public String toString() {
return "Person{" +
"id=" + id +
", father=" + father +
'}';
}
static class Father {
private String name;
private String surname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
#Override
public String toString() {
return "Father{" +
"name='" + name + '\'' +
", surname='" + surname + '\'' +
'}';
}
}
}
Above code prints:
{
"id" : 1909,
"name" : "Wit",
"surname" : "Pil"
}
Person{id=1909, father=Father{name='Wit', surname='Pil'}}
I've tested it for many version since 2.6.7 and it works fine.
I have the following JSON text (REST API URL SOURCE). How can I parse it to get ID, name, phone,city etc:
{"ID":1,"name":"aaa","phone":["345345345","1244","743"],"city":"asdasd"}
{"ID":2,"name":"bbb","phone":["234234","235","124"]}
{"ID":3,"name":"ccc","phone":["4234","6236","123"],"city":"jhjk"}
thanks.
EDIT:
I Run this code:
String var1 = output;
JSONObject obj;
try {
obj = new JSONObject(var1);
String a = obj.getString("name");
String b = obj.getString("phone");
String c = obj.getString("city");
System.out.println("name:" + a);
System.out.println("phone:" + b);
System.out.println("city:" + c);
and I got "phone" as a string .
someone can add the code to parse the phone line?
You can use Gson to parse the JSON. Simply create a class for this and Gson will do the parsing for you.
class MyClass{
#SerializedName("ID")
String ID;
#SerializedName("name")
String name;
#SerializedName("phone")
List<String> phone;
#SerializedName("city")
String city;
public MyClass(String ID, String name, List<String> phone, String city) {
this.ID = ID;
this.name = name;
this.phone = phone;
this.city = city;
}
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getPhone() {
return phone;
}
public void setPhone(List<String> phone) {
this.phone = phone;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
then in your main class or activity:
MyClass myclass= new Gson().fromJSON(jsonString,MyClass.class);
System.out.println(myclass.getID());
Make use of org.json libarary.
Afterwards, create an instance of JSONObject and JSONArray to parse the JSON String
Say I have a Yaml file like this,
people:
- name : Joe
surname : Barber
age : 16
- name : Andy
surname : Lots
age : 17
And I have a class like this,
public class people {
private String name;
private String surname;
private String age;
<!-- With getters and setters -->
}
How would i go about getting a list of people objects from the Yaml file?
Just getting the value from a key in the file is fairly simple but mapping it to a collection of objects is not.
I am using the snakeYaml lib.
i hope this can help you.
public class StackOverflow {
public static void main(String[] args) {
final URL resource = StackOverflow.class.getResource("people.yaml");
final Constructor peopleContructor = new Constructor(Group.class);
final TypeDescription peopleDescription = new TypeDescription(People.class);
peopleDescription.putMapPropertyType("people", People.class, Object.class);
peopleContructor.addTypeDescription(peopleDescription);
final Yaml yaml = new Yaml(peopleContructor);
try {
final Group group = (Group) yaml.load(resource.openStream());
for (final People people : group.getPeople()) {
System.out.println(people);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static class People {
private String name;
private String surname;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
#Override
public String toString() {
return "People: {name: " + this.name + ", surname: " + this.surname + ", age: " + this.age + "}";
}
}
public static class Group {
private List<People> people;
public List<People> getPeople() {
return people;
}
public void setPeople(List<People> people) {
this.people = people;
}
}}
I would like to convert the following string/ JSONObject to POJO,
{"list":["\r\n{\r\n\"id\":\"1\",\r\n\"protocol\":\"udp\",\r\n\"srcPorts= \":\"3000-4000 \",\r\n\"destPorts\":\"1790-2000\"\r\n}","\r\n{\r\n\"id\":\"2\",\r\n \"protocol\":\"tcp\",\r\n\"srcPorts\":\"3000-4000\",\r\n\"destPorts\":\"1790-2000 \"\r\n}"],"user":"\r\n{\r\n\"name\":\"John\",\r\n\"address\":\"x.x.x.x\",\r\n\"email \":\"john#p.com\"\r\n}"}
How do I convert to Pojo using Jackson ObjectMapper.
The 2 Pojo classes are as follows.
The user part in the string above should map to the java file - User.java
public class User
{
private String name;
private String address;
private String email;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAddress()
{
return address;
}
public void setaddress(String Address)
{
this.address = address;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
}
The List part in the string above should map to the java file - TestCase.java
public class TestCase
{
private String id;
private String protocol;
private String srcPorts;
private String destPorts;
public String getProtocol()
{
return protocol;
}
public void setProtocol(String protocol)
{
this.protocol = protocol;
}
public String getSrcPorts()
{
return srcPorts;
}
public void setSrcPorts(String srcPorts)
{
this.srcPorts = srcPorts;
}
public String getDestPorts()
{
return destPorts;
}
public void setDestPorts(String destPorts)
{
this.destPorts = destPorts;
}
public String getID()
{
return id;
}
public void setID(String id)
{
this.id = id;
}
}
Following code should help.
class ParseJson{
private User user;
private TestCase testCase;
//getter and setter methods
}
//and then call objectMapper -
String jsonString = "";//Json input
ObjectMapper mapper = new ObjectMapper();
ParseJson parsedJson = mapper.readValue(jsonString, ParseJson.class);
User user = parsedJson.getUser();
TestCase testCase = parsedJson.getTestCase();
Since your JSON object does not contain any type information, the best approach would be to use a custom deserializer class for Jackson, at least for the outer class. Alternatively, you can try annotating your POJO classes with Jackson annotations, and hope that the Right Thing happens.
In any case, you will have to make Jackson aware of your context by calling one of the ObjectMapper.readValue() methods with the proper class type argument, so that Jackson will know what it is that is being deserialized.