I'm trying to figure out how to convert a Jackson object into a JSONObject?
What I've tried, however I don't believe this is the correct approach.
public JSONObject toJSON() throws IOException {
ObjectMapper mapper = new ObjectMapper();
return new JSONObject(mapper.writeValueAsString(new Warnings(warnings)));
}
The way you are doing is work fine, because i also use that way to make a JSONobject.
here is my code
public JSONObject getRequestJson(AccountInquiryRequestVO accountInquiryRequestVO) throws JsonGenerationException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
JSONObject jsonAccountInquiry;
jsonAccountInquiry=new JSONObject(mapper.writeValueAsString(accountInquiryRequestVO));
return jsonAccountInquiry;
}
its working fine for me. but you can always use JsonNode also
here is the sample code for that
JsonNode jsonNode=mapper.valueToTree(accountInquiryRequestVO);
its very easy to use.
Right now, you are serializing your Pojo to a String, then parsing that String and converting it into a HashMap style object in the form of JSONObject.
This is very inefficient and doesn't accomplish anything of benefit.
Jackson already provides an ObjectNode class for interacting with your Pojo as a JSON object. So just convert your object to an ObjectNode. Here's a working example
public class Example {
public static void main(String[] args) throws Exception {
Pojo pojo = new Pojo();
pojo.setAge(42);
pojo.setName("Sotirios");
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = mapper.valueToTree(pojo);
System.out.println(node);
}
}
class Pojo {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Otherwise, the way you are doing it is fine.
Related
I need to serialize/deserialize a POJO with enum. I have the following DTO:
public enum MyEnum {
VAL1("val1"),
VAL2("val2") {
#Override
public String getValue() {
return "test2";
}
};
private final String name;
MyEnum(String name) {
this.name = name;
}
public String getValue() {
return name;
}
}
public class MyPojo {
public MyEnum prop;
}
public static void main(String... args) {
Gson gson = new GsonBuilder().registerTypeAdapter(MyEnum.class, new MyEnumSeserializer());
MyPojo p = new MyPojo();
p.prop = MyEnum.VAL2; // and I get MyEnum$1.class and My serializer doesn't work
String json = gson.toJson(p);
MyPojo p1 = gson.fromJson(json, MyPojo.class);
}
How can I write a custom serializer/deserializer for proxy classes using Gson library? I can't use another library.
I've been found the solution. Need to change
new GsonBuilder().registerTypeAdapter(MyEnum.class, new MyEnumSeserializer());
to
new GsonBuilder(). registerTypeHierarchyAdapter(MyEnum.class, new MyEnumSeserializer());
and all work fine.
I have a 'Example' Pojo class as mentioned below.
Can any one tel to save instance of Example class to YAML file using Jackson.
public class Example {
String name;
int value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
Jackson has a module that supports YAML. Ensure that you add the required dependency to your project, then you can use it as following:
// Create an ObjectMapper mapper for YAML
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
// Write object as YAML file
mapper.writeValue(new File("/path/to/yaml/file"), example);
Alternatively you can write your object as a string:
// Write object as YAML string
String yaml = mapper.writeValueAsString(example);
Consider the following json, getting from an public API:
anyObject : {
attributes: [
{
"name":"anyName",
"value":"anyValue"
},
{
"name":"anyName",
"value":
{
"key":"anyKey",
"label":"anyLabel"
}
}
]
}
As you can see, sometimes the value is a simple string and sometimes its an object. Is it somehow possible to deserialize those kind of json-results, to something like:
class AnyObject {
List<Attribute> attributes;
}
class Attribute {
private String key;
private String label;
}
How would I design my model to cover both cases. Is that possible ?
Despite being hard to manage as others have pointed out, you can do what you want. Add a custom deserializer to handle this situation. I rewrote your beans because I felt your Attribute class was a bit misleading. The AttributeEntry class in the object that is an entry in that "attributes" list. The ValueObject is the class that represents that "key"/"label" object. Those beans are below, but here's the custom deserializer. The idea is to check the type in the JSON, and instantiate the appropriate AttributeEntry based on its "value" type.
public class AttributeDeserializer extends JsonDeserializer<AttributeEntry> {
#Override
public AttributeEntry deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode root = p.readValueAsTree();
String name = root.get("name").asText();
if (root.get("value").isObject()) {
// use your object mapper here, this is just an example
ValueObject attribute = new ObjectMapper().readValue(root.get("value").asText(), ValueObject.class);
return new AttributeEntry(name, attribute);
} else if (root.get("value").isTextual()) {
String stringValue = root.get("value").asText();
return new AttributeEntry(name, stringValue);
} else {
return null; // or whatever
}
}
}
Because of this ambiguous type inconvenience, you will have to do some type checking throughout your code base.
You can then add this custom deserializer to your object mapper like so:
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(AttributeEntry.class, new AttributeDeserializer());
objectMapper.registerModule(simpleModule);
Here's the AttributeEntry:
public class AttributeEntry {
private String name;
private Object value;
public AttributeEntry(String name, String value) {
this.name = name;
this.value = value;
}
public AttributeEntry(String name, ValueObject attributes) {
this.name = name;
this.value = attributes;
}
/* getters/setters */
}
Here's the ValueObject:
public class ValueObject {
private String key;
private String label;
/* getters/setters */
}
I have an input JSON Node as following
"headers" : {
"name1" : "value1",
"name2" : "value2"
}
My Java class looks as follows :
public class OptionalHeader{
private String name;
private String value;
public OptionalHeader() {
super();
}
public OptionalHeader(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
I want to create an arrayList of OptionalHeader like below from the JsonNode.
List<OptionalHeader> optionalHeaders = new ArrayList<OptionalHeader>();
Any help would be appreciated. Thanks :)
Thanks for all the replies :)
I required the JsonNode coming via REST request containing key->value pairs to be converted into an ArrayList<OptionalHeader>, see the OptionalHeader class in question.
finally did it using following:
(getting it as JsonNode in my POJO) coming via REST request. I used below in my setter.
public void setOptHeaders(JsonNode optHeaders) throws JsonParseException, JsonMappingException, IOException {
this.optHeaders = optHeaders;
List<OptionalHeader> allHeaders = new ArrayList<OptionalHeader>();
Iterator<Entry<String, JsonNode>> nodeIterator = optHeaders.fields();
while (nodeIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = (Map.Entry<String, JsonNode>) nodeIterator.next();
OptionalHeader header = new OptionalHeader(entry.getKey(),entry.getValue().asText());
allHeaders.add(header);
}
optionalEmailHeaders.addAll(allHeaders);
}
then following in the getter to convert it back.
public JsonNode getOptHeaders() {
final ObjectMapper mapper = new ObjectMapper();
final Map<String, String> map = new HashMap<String, String>();
for (final OptionalHeader data: optionalEmailHeaders)
map.put(data.getName(), data.getValue());
optHeaders = mapper.valueToTree(map);
return optHeaders;
}
Jackson mapper is there which can map Java Objects from/to JSON objects.
You can get the Jackson API from here.
Try saving your JSON string into a file eg. 'headers.json'.
Jackson provides a ObjectMapper class and you can use its readValue( File file, Class class) method to get the Java object from JSON like :-
ObjectMapper mapper = new ObjectMapper();
OptionalHeader optHeader= mapper.readValue(new File("c:\\headers.json"), OptionalHeader .class);
You can use the same link for getting the docs & read more about it.
Have a relatively simple (I think) issue, but being a novice to JSON cannot seem to find a neat solution.
I have an Entity object with Id field as type Integer. However, the incoming Json data to be mapped has the id as a string.
With this a straightforward map does not seem to be possible. Is there a way to change the string data in the JSON to an integer, before mapping?
Example Json data
{"Id": "021", "userAge": 99}
Example Entity
#Entity
public class User{
#id
int userId;
int userAge;
}
Many Thanks.
You don't need to.
Jackson is smart enough to convert a JSON string to a numerical value if the target field is numerical.
It's not obvious what the leading 0 is meant to represent, but Jackson will simply ignore it.
Also, if your field name is different in Java, you'll need #JsonProperty("theJsonName").
public class Jackson {
public static void main(String[] args) throws Exception {
String json = "{\"userId\": \"021\", \"userAge\": 99}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
System.out.println(user.userId);
}
}
class User {
int userId;
int userAge;
public void setUserId(int userId) {
this.userId = userId;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
}
prints
21
You can write a custom jackson deserializer to cope with this behaviour. There's an good blog post on this topic here.
public class ItemDeserializer extends JsonDeserializer<Item> {
#Override
public Item deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
int id = Integer.parseInt(node.get("userId").asText());
int userAge = (Integer) ((IntNode) node.get("userAge")).numberValue();
return new Item(id, userAge);
}
}