Can JSONObject hold large formatted Double value using java? - java

Greetings,
I have JSONObject that contain payment information, today our customer asked for 10 digit number formatted as (1234567890.12), i have parameter total_amount , when i set this parameter value {"total_amount":123456789.23} it shown in server like {"total_amount":1.2345678923E8} , is there anyway that i can make JSONObject hold it as 123456789.23

You can have a deserialiser and utilise a fasterxml(com.fasterxml.jackson.databind.annotation.JsonSerialize) annotation
deserialiser class:
class DecimalJsonSerializer extends JsonSerializer<Double> {
#Override
public void serialize(Double value, JsonGenerator jsonGenerator, SerializerProvider provider)
throws IOException {
jsonGenerator.writeNumber(String.format("%.1f", value));
}
}
And the annotation on your field should look like:
#JsonSerialize(using = DecimalJsonSerializer.class)
private Double total_amount;

Related

Is there a way to serialize this class?

#JsonSerialize(using = TestDefSerializer.class)
public class TestDef{
private List<TestStep> steps = new LinkedList<>();
private String name;
} //Getter and Setters are defined
I can't seem to figure out a way after this
public class TestDefSerializer extends StdSerializer<TestDef> {
public TestDefSerializer(Class<TestDef> t) {
super(t);
}
public TestDefSerializer(){
this(TestDef.class);
}
#Override
public void serialize(TestDef testDefinition, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
// What should go here in order to serialize List<TestStep> ???
}
}
TestStep has a couple of fields namely responseDef (which has path , method) , requestDef (mathcing , status) etc. I wish to skip a couple of fields in responseDef and requestDef
There are chances you don't even need to implement a
TestDefSerializer at all , because Jackson is probably
smart enough to pick up enough information from the getters
of your TestDef class.
Just omit the line
#JsonSerialize(using = TestDefSerializer.class)
on your TestDef class and check if this will already
produce the JSON output you want.
But anyway, here is how to proceed if you want to
implement your own TestDefSerializer.
Look up the the API docu of JsonGenerator.
It describes all the write... methods available
for writing the JSON pieces.
For example, there is method writeStartArray() for writing a [,
and writeEndArray() for writing a ].
So in your TestDefSerializer class you may end up
with a serialize method looking like this:
#Override
public void serialize(TestDef testDefinition, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject(); // write {
jsonGenerator.writeFieldName("name"); // write "name":
jsonGenerator.writeString(testDefinition.getName());
jsonGenerator.writeFieldName("steps"); // write "steps":
jsonGenerator.writeStartArray(); // write [
for (TestStep testStep : testDefinition.getSteps()) {
jsonGenerator.writeObject(testStep); // this will invoke the serializer for TestStep
}
jsonGenerator.writeEndArray(); // write ]
jsonGenerator.writeEndObject(); // write }
}

Jackson JsonInclude.Include.NON_NULL is not working with custom serialiser

I have a custom serialiser which extends JsonSerializer<T>
and in the ObjectMapper I have included setSerializationInclusion(JsonInclude.Include.NON_NULL).
I still see null field in response.
Currently, I ignore them by checking null for each property. I have almost 15 objects and it's very difficult to add null checking to each property. Object I am using is shared by my applications, that is the reason why I am using custom serialiser to name the properties
#Override
public void serialize(Person personBean, JsonGenerator jgen, SerializerProvider provider) throws IOException {
if(personBean.getFirstName() != null){
jgen.writeStringField("firstname", personBean.getFirstName() );
}
//etc...
}
How to avoid null check for each property and implement some generic code to avoid null values in my serialised response.
Unfortunately, when we write custom serialiser we need to take care about null values by ourself. To make it at least a little bit better we can add new writeStringField method and use it. For example:
class PersonJsonSerializer extends JsonSerializer<Person> {
#Override
public void serialize(Person value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
writeStringField(gen, "firstname", value.getFirstName());
gen.writeEndObject();
}
private void writeStringField(JsonGenerator gen, String fieldName, String value) throws IOException {
if (value != null) {
gen.writeStringField(fieldName, value);
}
}
}
If you need to change only property names you can use PropertyNamingStrategy option. There is a few possibilities like:
LOWER_CASE - Naming convention in which all words of the logical name are in lower case, and no separator is used between words.
KEBAB_CASE - Naming convention used in languages like Lisp, where words are in lower-case letters, separated by hyphens.
For more check documentation
Example ObjectMapper customisation could look like:
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE);
If there is no predefined strategy which satisfies your need you can use JsonView annotation.

Read #JsonProperty dynamically from config

I am developing a Spring boot application which uses Jackson annotations.
I want to read value of #JsonProperty from a config, instead of using constant string.
Example JSON input
{"s":12}
Code
I want to read property from my config:
#JsonProperty("${myconfig.fieldAlias.stream}")
private Integer stream;
instead of
#JsonProperty("s")
private Integer stream;
Issue
While executing the code above using config:
variable "s" is not identified as stream
unless I use constant #JsonProperty("s"), which is not desired.
Is it possible to use dynamic JsonProperty values? If so, what is the proper way to do so?
The name given to #JsonProperty must be statically given. What you can do is to overwrite the given name dynamically, by implementing a custom serializer for the propery:
public static class StreamSerializer extends JsonSerializer<Integer> {
#Override public void serialize(Integer value, JsonGenerator jsonGenerator, SerializerProvider provider)
throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("s", your_dynamic_name_here);// dynamic field name
jsonGenerator.writeEndObject();
}
}
and use it like this:
#JsonProperty("s")
#JsonSerialize(using = StreamSerializer.class)
private Integer stream;

Jackson Custom String to Date Serializer

I am trying to make Jackson to parse String to Date with given format. I came up with the following code for now:
#JsonIgnoreProperties(ignoreUnknown = true)
public class EventData implements Serializable {
private transient SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
#JsonSerialize(using = StringToDateSerializer.class, as = Date.class)
private Date eventStart;
public class StringToDateSerializer extends JsonSerializer<String> {
#Override
public void serialize(String tmpString,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider)
throws IOException, JsonProcessingException {
try {
jsonGenerator.writeObject(formatter.parse(tmpString));
} catch (ParseException e) {
}
}
}
}
But my only field eventStart always get populated with NULL. Also, it does not stops on breakpoint inside try/catch block as if it is never been invoked. The other (non custom) fields are populated fine.
What I am doing wrong? Thanks
If you are trying to convert JSON into EventData where one of the fields is a data string then you need to deserialize it (serialization is process when you convert your Java object into the JSON/stream of bytes).
Jackson provide better way how to handle Date format:
http://wiki.fasterxml.com/JacksonFAQDateHandling
Since Jackson 2.0 you can use JsonFormat where you can specify custom date format
public class DateStuff {
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd,HH:00", timezone="CET")
public Date creationTime;
}

Jackson - converting java object to json - Need all key keys to upper case

Need your help on conversion of java objects to json.
current the json result showing all the key in small letter case, i need it to be upper case.
ObjectMapper mapper = new ObjectMapper();
Writer strWriter = new StringWriter();
mapper.writeValue(strWriter, obj);
String jsonString= strWriter.toString();
and the result is
[{"flags":"1","name":"Peter","location":"London","startDate":"2012-01-06 00:00"}]
but i want results like this (all key key value should be in UPPER CASE):
[{"FLAGS":"YU","NAME":"Peter","LOCATION":"London","STARTDATE":"2012-01-06 00:00"}]
and also is it possible to get like this also (key first letter in upper case):
[{"Flags":"1","Name":"Peter","Location":"London","StartDate":"2012-01-06 00:00"}]
Can anyone help me on this.
Thanks in advance.
There are multiple ways to do it with Jackson.
Annotations
You could annotate your object with #JsonProperty annotations on your fields or on your getter methods.
Example:
#JsonProperty("Name")
public final String name;
#JsonProperty("Location")
public String getLocation() {
return location;
}
Implement JsonSerializableWithType interface
#Override
public void serialize(final JsonGenerator jG, final SerializerProvider p)
throws IOException, JsonProcessingException
{
serializeWithType(jG, p, null);
}
#Override
public void serializeWithType(final JsonGenerator jG, final SerializerProvider p, final TypeSerializer typeSer)
throws IOException, JsonProcessingException
{
// here you can do your own serialization
}
I would advice to use the #JsonNaming annotation on class level.
Yet afaik there is no strategy out there to fit your needs for total uppercase. But you can probably just write your own.
In my case I needed first character uppercase. So I used the existing
#JsonNaming(value = UpperCamelCaseStrategy.class).

Categories