Java 11497 (#12399)

* Added/created parent module (json-modules)

* moved json(submodule) to json-modules(parent)

* moved json-2(submodule) to json-modules(parent)

* moved json-path(submodule) to json-modules(parent)

* moved gson(submodule) to json-modules(parent)

* deleted sub-modules that we moved to json-modules

Co-authored-by: panagiotiskakos <panagiotis.kakos@libra-is.com>
This commit is contained in:
panos-kakos
2022-06-24 17:28:34 +01:00
committed by GitHub
parent 86d5df3e85
commit 7866faf761
163 changed files with 377 additions and 336 deletions

3
json-modules/README.md Normal file
View File

@@ -0,0 +1,3 @@
## JSON
This module contains modules about JSON.

13
json-modules/gson/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
*.class
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
# Packaged files #
*.jar
*.war
*.ear

View File

@@ -0,0 +1,16 @@
## GSON
This module contains articles about Gson
### Relevant Articles:
- [Gson Deserialization Cookbook](https://www.baeldung.com/gson-deserialization-guide)
- [Jackson vs Gson](https://www.baeldung.com/jackson-vs-gson)
- [Exclude Fields from Serialization in Gson](https://www.baeldung.com/gson-exclude-fields-serialization)
- [Save Data to a JSON File with Gson](https://www.baeldung.com/gson-save-file)
- [Convert JSON to a Map Using Gson](https://www.baeldung.com/gson-json-to-map)
- [Working with Primitive Values in Gson](https://www.baeldung.com/java-gson-primitives)
- [Convert String to JsonObject with Gson](https://www.baeldung.com/gson-string-to-jsonobject)
- [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field)
- [Serializing and Deserializing a List with Gson](https://www.baeldung.com/gson-list)
- [Compare Two JSON Objects with Gson](https://www.baeldung.com/gson-compare-json-objects)

74
json-modules/gson/pom.xml Normal file
View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>gson</artifactId>
<version>0.1-SNAPSHOT</version>
<name>gson</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>json-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<!-- utils -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- marshalling -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
</dependencies>
<build>
<finalName>gson</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<properties>
<gson.version>2.8.0</gson.version>
<joda-time.version>2.9.6</joda-time.version>
<guava.version>11.0.2</guava.version>
</properties>
</project>

View File

@@ -0,0 +1,57 @@
package com.baeldung.gson.entities;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
public class ActorGson {
private String imdbId;
private Date dateOfBirth;
private List<String> filmography;
public ActorGson(String imdbId, Date dateOfBirth, List<String> filmography) {
super();
this.imdbId = imdbId;
this.dateOfBirth = dateOfBirth;
this.filmography = filmography;
}
@Override
public String toString() {
return "ActorGson [imdbId=" + imdbId + ", dateOfBirth=" + formatDateOfBirth() + ", filmography=" + filmography + "]";
}
public String getImdbId() {
return imdbId;
}
public void setImdbId(String imdbId) {
this.imdbId = imdbId;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public List<String> getFilmography() {
return filmography;
}
public void setFilmography(List<String> filmography) {
this.filmography = filmography;
}
private String formatDateOfBirth() {
final DateFormat formatter = new SimpleDateFormat("EEE MMM dd hh:mm:ss zzz yyyy");
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
return formatter.format(dateOfBirth);
}
}

View File

@@ -0,0 +1,5 @@
package com.baeldung.gson.entities;
public abstract class Animal {
public String type = "Animal";
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.gson.entities;
public class Cow extends Animal {
private String breed;
public Cow() {
breed = "Jersey";
type = "Cow";
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.gson.entities;
public class Dog extends Animal {
private String petName;
public Dog() {
petName = "Milo";
type = "Dog";
}
public String getPetName() {
return petName;
}
public void setPetName(String petName) {
this.petName = petName;
}
}

View File

@@ -0,0 +1,36 @@
package com.baeldung.gson.entities;
public class Employee {
private int id;
private String name;
private String address;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
}

View File

@@ -0,0 +1,48 @@
package com.baeldung.gson.entities;
import java.util.List;
public class Movie {
private String imdbId;
private String director;
private List<ActorGson> actors;
public Movie(String imdbID, String director, List<ActorGson> actors) {
super();
this.imdbId = imdbID;
this.director = director;
this.actors = actors;
}
@Override
public String toString() {
return "Movie [imdbId=" + imdbId + ", director=" + director + ", actors=" + actors + "]";
}
public String getImdbID() {
return imdbId;
}
public void setImdbID(String imdbID) {
this.imdbId = imdbID;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public List<ActorGson> getActors() {
return actors;
}
public void setActors(List<ActorGson> actors) {
this.actors = actors;
}
}

View File

@@ -0,0 +1,46 @@
package com.baeldung.gson.entities;
import com.google.gson.annotations.Expose;
import java.util.List;
public class MovieWithNullValue {
@Expose
private String imdbId;
private String director;
@Expose
private List<ActorGson> actors;
public MovieWithNullValue(String imdbID, String director, List<ActorGson> actors) {
super();
this.imdbId = imdbID;
this.director = director;
this.actors = actors;
}
public String getImdbID() {
return imdbId;
}
public void setImdbID(String imdbID) {
this.imdbId = imdbID;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public List<ActorGson> getActors() {
return actors;
}
public void setActors(List<ActorGson> actors) {
this.actors = actors;
}
}

View File

@@ -0,0 +1,49 @@
package com.baeldung.gson.entities;
import java.util.Objects;
public class MyClass {
private int id;
private String name;
public MyClass(int id, String name) {
this.id = id;
this.name = name;
}
public MyClass() { }
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MyClass myClass = (MyClass) o;
return id == myClass.id && Objects.equals(name, myClass.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.gson.entities;
public class User {
private int id;
private String name;
private transient String nationality;
public User(int id, String name, String nationality) {
this.id = id;
this.name = name;
this.nationality = nationality;
}
public User(int id, String name) {
this(id, name, null);
}
}

View File

@@ -0,0 +1,40 @@
package com.baeldung.gson.entities;
import com.google.gson.annotations.SerializedName;
public class Weather {
@SerializedName(value = "location", alternate = "place")
private String location;
@SerializedName(value = "temp", alternate = "temperature")
private int temp;
@SerializedName(value = "outlook", alternate = "weather")
private String outlook;
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public int getTemp() {
return temp;
}
public void setTemp(int temp) {
this.temp = temp;
}
public String getOutlook() {
return outlook;
}
public void setOutlook(String outlook) {
this.outlook = outlook;
}
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.gson.primitives.models;
public class BooleanExample {
public boolean value;
public String toString() {
return "{boolean: " + value + "}";
}
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.gson.primitives.models;
public class ByteExample {
public byte value = (byte) 1;
public String toString() {
return "{byte: " + value + "}";
}
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.gson.primitives.models;
public class CharExample {
public char value;
public String toString() {
return "{char: " + value + "}";
}
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.gson.primitives.models;
public class DoubleExample {
public double value;
public String toString() {
return "{float: " + value + "}";
}
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.gson.primitives.models;
public class FloatExample {
public float value;
public String toString() {
return "{float: " + value + "}";
}
}

View File

@@ -0,0 +1,6 @@
package com.baeldung.gson.primitives.models;
public class InfinityValuesExample {
public float negativeInfinity;
public float positiveInfinity;
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.gson.primitives.models;
public class LongExample {
public long value = 1;
public String toString() {
return "{byte: " + value + "}";
}
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.gson.primitives.models;
public class PrimitiveBundle {
public byte byteValue;
public short shortValue;
public int intValue;
public long longValue;
public float floatValue;
public double doubleValue;
public boolean booleanValue;
public char charValue;
public String toString() {
return "{" + "byte: " + byteValue + ", " + "short: " + shortValue + ", "
+ "int: " + intValue + ", " + "long: " + longValue + ", "
+ "float: " + floatValue + ", " + "double: " + doubleValue + ", "
+ "boolean: " + booleanValue + ", " + "char: " + charValue + "}";
}
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.gson.primitives.models;
public class PrimitiveBundleInitialized {
// @formatter:off
public byte byteValue = (byte) 1;
public short shortValue = (short) 1;
public int intValue = 1;
public long longValue = 1L;
public float floatValue = 1.0f;
public double doubleValue = 1;
// @formatter:on
public String toString() {
return "{" + "byte: " + byteValue + ", " + "short: " + shortValue + ", "
+ "int: " + intValue + ", " + "long: " + longValue + ", "
+ "float: " + floatValue + ", " + "double: " + doubleValue + "}";
}
}

View File

@@ -0,0 +1,46 @@
package com.baeldung.gson.serialization;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import com.baeldung.gson.entities.ActorGson;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
public class ActorGsonDeserializer implements JsonDeserializer<ActorGson> {
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
@Override
public ActorGson deserialize(JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
final JsonObject jsonObject = json.getAsJsonObject();
final JsonElement jsonImdbId = jsonObject.get("imdbId");
final JsonElement jsonDateOfBirth = jsonObject.get("dateOfBirth");
final JsonArray jsonFilmography = jsonObject.getAsJsonArray("filmography");
final ArrayList<String> filmList = new ArrayList<String>();
if (jsonFilmography != null) {
for (int i = 0; i < jsonFilmography.size(); i++) {
filmList.add(jsonFilmography.get(i).getAsString());
}
}
ActorGson actorGson = null;
try {
actorGson = new ActorGson(jsonImdbId.getAsString(), sdf.parse(jsonDateOfBirth.getAsString()), filmList);
} catch (final ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return actorGson;
}
}

View File

@@ -0,0 +1,33 @@
package com.baeldung.gson.serialization;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.baeldung.gson.entities.ActorGson;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.stream.Collectors;
public class ActorGsonSerializer implements JsonSerializer<ActorGson> {
private SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
@Override
public JsonElement serialize(ActorGson actor, Type type, JsonSerializationContext jsonSerializationContext) {
JsonObject actorJsonObj = new JsonObject();
actorJsonObj.addProperty("<strong>IMDB Code</strong>", actor.getImdbId());
actorJsonObj.addProperty("<strong>Date Of Birth</strong>", actor.getDateOfBirth() != null ? sdf.format(actor.getDateOfBirth()) : null);
actorJsonObj.addProperty("<strong>N° Film:</strong> ", actor.getFilmography() != null ? actor.getFilmography().size() : null);
actorJsonObj.addProperty("filmography", actor.getFilmography() != null ? convertFilmography(actor.getFilmography()) : null);
return actorJsonObj;
}
private String convertFilmography(List<String> filmography) {
return filmography.stream().collect(Collectors.joining("-"));
}
}

View File

@@ -0,0 +1,35 @@
package com.baeldung.gson.serialization;
import com.google.gson.Gson;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import com.baeldung.gson.entities.Animal;
public class AnimalDeserializer implements JsonDeserializer<Animal> {
private String animalTypeElementName;
private Gson gson;
private Map<String, Class<? extends Animal>> animalTypeRegistry;
public AnimalDeserializer(String animalTypeElementName) {
this.animalTypeElementName = animalTypeElementName;
this.gson = new Gson();
this.animalTypeRegistry = new HashMap<>();
}
public void registerBarnType(String animalTypeName, Class<? extends Animal> animalType) {
animalTypeRegistry.put(animalTypeName, animalType);
}
public Animal deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
JsonObject animalObject = json.getAsJsonObject();
JsonElement animalTypeElement = animalObject.get(animalTypeElementName);
Class<? extends Animal> animalType = animalTypeRegistry.get(animalTypeElement.getAsString());
return gson.fromJson(animalObject, animalType);
}
}

View File

@@ -0,0 +1,63 @@
package com.baeldung.gson.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Map;
import java.util.stream.Collectors;
import com.baeldung.gson.entities.Employee;
import com.google.gson.*;
public class MapDeserializer implements JsonDeserializer<Map<String, Object>> {
@Override
public Map<String, Object> deserialize(JsonElement elem, Type type, JsonDeserializationContext context) throws JsonParseException {
return elem.getAsJsonObject()
.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().isJsonPrimitive() ?
toPrimitive(e.getValue().getAsJsonPrimitive(), context)
: context.deserialize(e.getValue(), Employee.class)
));
}
private Object toPrimitive(JsonPrimitive jsonValue, JsonDeserializationContext context) {
if (jsonValue.isBoolean())
return jsonValue.getAsBoolean();
else if (jsonValue.isString())
return jsonValue.getAsString();
else {
BigDecimal bigDec = jsonValue.getAsBigDecimal();
Long l;
Integer i;
if ((i = toInteger(bigDec)) != null) {
return i;
} else if ((l = toLong(bigDec)) != null) {
return l;
} else {
return bigDec.doubleValue();
}
}
}
private Long toLong(BigDecimal val) {
try {
return val.toBigIntegerExact().longValue();
} catch (ArithmeticException e) {
return null;
}
}
private Integer toInteger(BigDecimal val) {
try {
return val.intValueExact();
} catch (ArithmeticException e) {
return null;
}
}
}

View File

@@ -0,0 +1,44 @@
package com.baeldung.gson.serialization;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
public class StringDateMapDeserializer implements JsonDeserializer<Map<String, Date>> {
private static final Logger logger = LoggerFactory.getLogger(StringDateMapDeserializer.class);
private SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
@Override
public Map<String, Date> deserialize(JsonElement elem, Type type, JsonDeserializationContext jsonDeserializationContext) {
System.out.println("Deserializer called");
logger.info("Deserializer called");
return elem.getAsJsonObject()
.entrySet()
.stream()
.filter(e -> e.getValue().isJsonPrimitive())
.filter(e -> e.getValue().getAsJsonPrimitive().isString())
.collect(Collectors.toMap(Map.Entry::getKey, e -> formatDate(e.getValue())));
}
private Date formatDate(JsonElement value) {
try {
return format.parse(value.getAsString());
} catch (ParseException ex) {
throw new JsonParseException(ex);
}
}
}

View File

@@ -0,0 +1,11 @@
package com.baeldung.gson.serializationwithexclusions;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.gson.serializationwithexclusions;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MyClass {
private long id;
private String name;
private String other;
private MySubClass subclass;
}

View File

@@ -0,0 +1,20 @@
package com.baeldung.gson.serializationwithexclusions;
import com.google.gson.annotations.Expose;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MyClassWithAnnotatedFields {
@Expose
private long id;
@Expose
private String name;
private String other;
@Expose
private MySubClassWithAnnotatedFields subclass;
}

View File

@@ -0,0 +1,16 @@
package com.baeldung.gson.serializationwithexclusions;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MyClassWithCustomAnnotatedFields {
private long id;
private String name;
@Exclude
private String other;
private MySubClassWithCustomAnnotatedFields subclass;
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.gson.serializationwithexclusions;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MyClassWithTransientFields {
private long id;
private String name;
private transient String other;
private MySubClassWithTransientFields subclass;
}

View File

@@ -0,0 +1,12 @@
package com.baeldung.gson.serializationwithexclusions;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MySubClass {
private long id;
private String description;
private String otherVerboseInfo;
}

View File

@@ -0,0 +1,15 @@
package com.baeldung.gson.serializationwithexclusions;
import com.google.gson.annotations.Expose;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MySubClassWithAnnotatedFields {
@Expose private long id;
@Expose private String description;
private String otherVerboseInfo;
}

View File

@@ -0,0 +1,14 @@
package com.baeldung.gson.serializationwithexclusions;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MySubClassWithCustomAnnotatedFields {
private long id;
private String description;
@Exclude
private String otherVerboseInfo;
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.gson.serializationwithexclusions;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class MySubClassWithTransientFields {
private long id;
private String description;
private transient String otherVerboseInfo;
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN"/>
<logger name="org.springframework.transaction" level="WARN"/>
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN"/>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@@ -0,0 +1,117 @@
package com.baeldung.gson.advance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.baeldung.gson.entities.Dog;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.baeldung.gson.entities.Animal;
import com.baeldung.gson.entities.Cow;
import com.baeldung.gson.entities.MyClass;
import com.baeldung.gson.serialization.AnimalDeserializer;
import org.junit.Test;
public class GsonAdvanceUnitTest {
@Test
public void givenListOfMyClass_whenSerializing_thenCorrect() {
List<MyClass> list = Arrays.asList(new MyClass(1, "name1"), new MyClass(2, "name2"));
Gson gson = new Gson();
String jsonString = gson.toJson(list);
String expectedString = "[{\"id\":1,\"name\":\"name1\"},{\"id\":2,\"name\":\"name2\"}]";
assertEquals(expectedString, jsonString);
}
@Test(expected = ClassCastException.class)
public void givenJsonString_whenIncorrectDeserializing_thenThrowClassCastException() {
String inputString = "[{\"id\":1,\"name\":\"name1\"},{\"id\":2,\"name\":\"name2\"}]";
Gson gson = new Gson();
List<MyClass> outputList = gson.fromJson(inputString, ArrayList.class);
assertEquals(1, outputList.get(0).getId());
}
@Test
public void givenJsonString_whenDeserializing_thenReturnListOfMyClass() {
String inputString = "[{\"id\":1,\"name\":\"name1\"},{\"id\":2,\"name\":\"name2\"}]";
List<MyClass> inputList = Arrays.asList(new MyClass(1, "name1"), new MyClass(2, "name2"));
Type listOfMyClassObject = new TypeToken<ArrayList<MyClass>>() {}.getType();
Gson gson = new Gson();
List<MyClass> outputList = gson.fromJson(inputString, listOfMyClassObject);
assertEquals(inputList, outputList);
}
@Test
public void givenPolymorphicList_whenSerializeWithTypeAdapter_thenCorrect() {
String expectedString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]";
List<Animal> inList = new ArrayList<>();
inList.add(new Dog());
inList.add(new Cow());
String jsonString = new Gson().toJson(inList);
assertEquals(expectedString, jsonString);
}
@Test
public void givenPolymorphicList_whenDeserializeWithTypeAdapter_thenCorrect() {
String inputString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]";
AnimalDeserializer deserializer = new AnimalDeserializer("type");
deserializer.registerBarnType("Dog", Dog.class);
deserializer.registerBarnType("Cow", Cow.class);
Gson gson = new GsonBuilder()
.registerTypeAdapter(Animal.class, deserializer)
.create();
List<Animal> outList = gson.fromJson(inputString, new TypeToken<List<Animal>>(){}.getType());
assertEquals(2, outList.size());
assertTrue(outList.get(0) instanceof Dog);
assertTrue(outList.get(1) instanceof Cow);
}
@Test
public void givenPolymorphicList_whenSerializeWithRuntimeTypeAdapter_thenCorrect() {
String expectedString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]";
List<Animal> inList = new ArrayList<>();
inList.add(new Dog());
inList.add(new Cow());
String jsonString = new Gson().toJson(inList);
assertEquals(expectedString, jsonString);
}
@Test
public void givenPolymorphicList_whenDeserializeWithRuntimeTypeAdapter_thenCorrect() {
String inputString = "[{\"petName\":\"Milo\",\"type\":\"Dog\"},{\"breed\":\"Jersey\",\"type\":\"Cow\"}]";
Type listOfAnimals = new TypeToken<ArrayList<Animal>>() {}.getType();
RuntimeTypeAdapterFactory<Animal> adapter = RuntimeTypeAdapterFactory.of(Animal.class, "type")
.registerSubtype(Dog.class)
.registerSubtype(Cow.class);
Gson gson = new GsonBuilder().registerTypeAdapterFactory(adapter).create();
List<Animal> outList = gson.fromJson(inputString, listOfAnimals);
assertEquals(2, outList.size());
assertTrue(outList.get(0) instanceof Dog);
assertTrue(outList.get(1) instanceof Cow);
}
}

View File

@@ -0,0 +1,265 @@
package com.baeldung.gson.advance;
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.Streams;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
/**
* Adapts values whose runtime type may differ from their declaration type. This
* is necessary when a field's type is not the same type that GSON should create
* when deserializing that field. For example, consider these types:
* <pre> {@code
* abstract class Shape {
* int x;
* int y;
* }
* class Circle extends Shape {
* int radius;
* }
* class Rectangle extends Shape {
* int width;
* int height;
* }
* class Diamond extends Shape {
* int width;
* int height;
* }
* class Drawing {
* Shape bottomShape;
* Shape topShape;
* }
* }</pre>
* <p>Without additional type information, the serialized JSON is ambiguous. Is
* the bottom shape in this drawing a rectangle or a diamond? <pre> {@code
* {
* "bottomShape": {
* "width": 10,
* "height": 5,
* "x": 0,
* "y": 0
* },
* "topShape": {
* "radius": 2,
* "x": 4,
* "y": 1
* }
* }}</pre>
* This class addresses this problem by adding type information to the
* serialized JSON and honoring that type information when the JSON is
* deserialized: <pre> {@code
* {
* "bottomShape": {
* "type": "Diamond",
* "width": 10,
* "height": 5,
* "x": 0,
* "y": 0
* },
* "topShape": {
* "type": "Circle",
* "radius": 2,
* "x": 4,
* "y": 1
* }
* }}</pre>
* Both the type field name ({@code "type"}) and the type labels ({@code
* "Rectangle"}) are configurable.
*
* <h3>Registering Types</h3>
* Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field
* name to the {@link #of} factory method. If you don't supply an explicit type
* field name, {@code "type"} will be used. <pre> {@code
* RuntimeTypeAdapterFactory<Shape> shapeAdapterFactory
* = RuntimeTypeAdapterFactory.of(Shape.class, "type");
* }</pre>
* Next register all of your subtypes. Every subtype must be explicitly
* registered. This protects your application from injection attacks. If you
* don't supply an explicit type label, the type's simple name will be used.
* <pre> {@code
* shapeAdapterFactory.registerSubtype(Rectangle.class, "Rectangle");
* shapeAdapterFactory.registerSubtype(Circle.class, "Circle");
* shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond");
* }</pre>
* Finally, register the type adapter factory in your application's GSON builder:
* <pre> {@code
* Gson gson = new GsonBuilder()
* .registerTypeAdapterFactory(shapeAdapterFactory)
* .create();
* }</pre>
* Like {@code GsonBuilder}, this API supports chaining: <pre> {@code
* RuntimeTypeAdapterFactory<Shape> shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
* .registerSubtype(Rectangle.class)
* .registerSubtype(Circle.class)
* .registerSubtype(Diamond.class);
* }</pre>
*/
public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
private final Class<?> baseType;
private final String typeFieldName;
private final Map<String, Class<?>> labelToSubtype = new LinkedHashMap<String, Class<?>>();
private final Map<Class<?>, String> subtypeToLabel = new LinkedHashMap<Class<?>, String>();
private final boolean maintainType;
private RuntimeTypeAdapterFactory(Class<?> baseType, String typeFieldName, boolean maintainType) {
if (typeFieldName == null || baseType == null) {
throw new NullPointerException();
}
this.baseType = baseType;
this.typeFieldName = typeFieldName;
this.maintainType = maintainType;
}
/**
* Creates a new runtime type adapter using for {@code baseType} using {@code
* typeFieldName} as the type field name. Type field names are case sensitive.
* {@code maintainType} flag decide if the type will be stored in pojo or not.
*/
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName, boolean maintainType) {
return new RuntimeTypeAdapterFactory<T>(baseType, typeFieldName, maintainType);
}
/**
* Creates a new runtime type adapter using for {@code baseType} using {@code
* typeFieldName} as the type field name. Type field names are case sensitive.
*/
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) {
return new RuntimeTypeAdapterFactory<T>(baseType, typeFieldName, false);
}
/**
* Creates a new runtime type adapter for {@code baseType} using {@code "type"} as
* the type field name.
*/
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType) {
return new RuntimeTypeAdapterFactory<T>(baseType, "type", false);
}
/**
* Registers {@code type} identified by {@code label}. Labels are case
* sensitive.
*
* @throws IllegalArgumentException if either {@code type} or {@code label}
* have already been registered on this type adapter.
*/
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type, String label) {
if (type == null || label == null) {
throw new NullPointerException();
}
if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) {
throw new IllegalArgumentException("types and labels must be unique");
}
labelToSubtype.put(label, type);
subtypeToLabel.put(type, label);
return this;
}
/**
* Registers {@code type} identified by its {@link Class#getSimpleName simple
* name}. Labels are case sensitive.
*
* @throws IllegalArgumentException if either {@code type} or its simple name
* have already been registered on this type adapter.
*/
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type) {
return registerSubtype(type, type.getSimpleName());
}
public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
if (type.getRawType() != baseType) {
return null;
}
final Map<String, TypeAdapter<?>> labelToDelegate
= new LinkedHashMap<String, TypeAdapter<?>>();
final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate
= new LinkedHashMap<Class<?>, TypeAdapter<?>>();
for (Map.Entry<String, Class<?>> entry : labelToSubtype.entrySet()) {
TypeAdapter<?> delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
labelToDelegate.put(entry.getKey(), delegate);
subtypeToDelegate.put(entry.getValue(), delegate);
}
return new TypeAdapter<R>() {
@Override public R read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement labelJsonElement;
if (maintainType) {
labelJsonElement = jsonElement.getAsJsonObject().get(typeFieldName);
} else {
labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName);
}
if (labelJsonElement == null) {
throw new JsonParseException("cannot deserialize " + baseType
+ " because it does not define a field named " + typeFieldName);
}
String label = labelJsonElement.getAsString();
@SuppressWarnings("unchecked") // registration requires that subtype extends T
TypeAdapter<R> delegate = (TypeAdapter<R>) labelToDelegate.get(label);
if (delegate == null) {
throw new JsonParseException("cannot deserialize " + baseType + " subtype named "
+ label + "; did you forget to register a subtype?");
}
return delegate.fromJsonTree(jsonElement);
}
@Override public void write(JsonWriter out, R value) throws IOException {
Class<?> srcType = value.getClass();
String label = subtypeToLabel.get(srcType);
@SuppressWarnings("unchecked") // registration requires that subtype extends T
TypeAdapter<R> delegate = (TypeAdapter<R>) subtypeToDelegate.get(srcType);
if (delegate == null) {
throw new JsonParseException("cannot serialize " + srcType.getName()
+ "; did you forget to register a subtype?");
}
JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject();
if (maintainType) {
Streams.write(jsonObject, out);
return;
}
JsonObject clone = new JsonObject();
if (jsonObject.has(typeFieldName)) {
throw new JsonParseException("cannot serialize " + srcType.getName()
+ " because it already defines a field named " + typeFieldName);
}
clone.add(typeFieldName, new JsonPrimitive(label));
for (Map.Entry<String, JsonElement> e : jsonObject.entrySet()) {
clone.add(e.getKey(), e.getValue());
}
Streams.write(clone, out);
}
}.nullSafe();
}
}

View File

@@ -0,0 +1,33 @@
package com.baeldung.gson.conversion;
import com.google.gson.*;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
public class JsonObjectConversionsUnitTest {
@Test
void whenUsingJsonParser_thenConvertToJsonObject() throws Exception {
// Example 1: Using JsonParser
String json = "{ \"name\": \"Baeldung\", \"java\": true }";
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
Assert.assertTrue(jsonObject.isJsonObject());
Assert.assertTrue(jsonObject.get("name").getAsString().equals("Baeldung"));
Assert.assertTrue(jsonObject.get("java").getAsBoolean() == true);
}
@Test
void whenUsingGsonInstanceFromJson_thenConvertToJsonObject() throws Exception {
// Example 2: Using fromJson
String json = "{ \"name\": \"Baeldung\", \"java\": true }";
JsonObject convertedObject = new Gson().fromJson(json, JsonObject.class);
Assert.assertTrue(convertedObject.isJsonObject());
Assert.assertTrue(convertedObject.get("name").getAsString().equals("Baeldung"));
Assert.assertTrue(convertedObject.get("java").getAsBoolean() == true);
}
}

View File

@@ -0,0 +1,61 @@
package com.baeldung.gson.deserialization;
public class Foo {
public int intValue;
public String stringValue;
public Foo(final int intValue, final String stringValue) {
this.intValue = intValue;
this.stringValue = stringValue;
}
public Foo(final String stringValue) {
this.stringValue = stringValue;
}
public Foo() {
super();
}
// API
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + intValue;
result = (prime * result) + ((stringValue == null) ? 0 : stringValue.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Foo other = (Foo) obj;
if (intValue != other.intValue) {
return false;
}
if (stringValue == null) {
if (other.stringValue != null) {
return false;
}
} else if (!stringValue.equals(other.stringValue)) {
return false;
}
return true;
}
@Override
public String toString() {
return "TargetClass{" + "intValue= " + intValue + ", stringValue= " + stringValue + '}';
}
}

View File

@@ -0,0 +1,26 @@
package com.baeldung.gson.deserialization;
import java.lang.reflect.Type;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
public class FooDeserializer implements JsonDeserializer<Foo[]> {
@Override
public Foo[] deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
final JsonArray jArray = json.getAsJsonArray();
final Foo[] scArray = new Foo[jArray.size()];
int index = 0;
for (final JsonElement jElement : jArray) {
final int i = jElement.getAsJsonObject().get("intValue").getAsInt();
final String s = jElement.getAsJsonObject().get("stringValue").getAsString();
scArray[index++] = new Foo(i, s);
}
return scArray;
}
}

View File

@@ -0,0 +1,21 @@
package com.baeldung.gson.deserialization;
import java.lang.reflect.Type;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
public class FooDeserializerFromJsonWithDifferentFields implements JsonDeserializer<Foo> {
@Override
public Foo deserialize(final JsonElement jElement, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
final JsonObject jObject = jElement.getAsJsonObject();
final int intValue = jObject.get("valueInt").getAsInt();
final String stringValue = jObject.get("valueString").getAsString();
return new Foo(intValue, stringValue);
}
}

View File

@@ -0,0 +1,14 @@
package com.baeldung.gson.deserialization;
import java.lang.reflect.Type;
import com.google.gson.InstanceCreator;
public class FooInstanceCreator implements InstanceCreator<Foo> {
@Override
public Foo createInstance(Type type) {
return new Foo("sample");
}
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.gson.deserialization;
public class FooWithInner {
public int intValue;
public String stringValue;
public InnerFoo innerFoo;
public FooWithInner(int intValue, String stringValue, String name) {
super();
this.intValue = intValue;
this.stringValue = stringValue;
this.innerFoo = new InnerFoo(name);
}
public class InnerFoo {
public String name;
public InnerFoo(String name) {
super();
this.name = name;
}
}
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.gson.deserialization;
public class GenericFoo<T> {
public T theValue;
public GenericFoo(final T value) {
theValue = value;
}
//
@Override
public final String toString() {
return "GenericTargetClass{" + "intField=" + theValue + '}';
}
}

View File

@@ -0,0 +1,39 @@
package com.baeldung.gson.deserialization;
import static org.junit.Assert.assertEquals;
import com.baeldung.gson.entities.Weather;
import org.junit.Test;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class GsonAlternateUnitTest {
@Test
public void givenTwoJsonFormats_whenDeserialized_thenWeatherObjectsCreated() throws Exception {
Gson gson = new GsonBuilder().create();
Weather weather = gson.fromJson("{" +
"\"location\": \"London\"," +
"\"temp\": 15," +
"\"weather\": \"Cloudy\"" +
"}", Weather.class);
assertEquals("London", weather.getLocation());
assertEquals("Cloudy", weather.getOutlook());
assertEquals(15, weather.getTemp());
weather = gson.fromJson("{" +
"\"place\": \"Lisbon\"," +
"\"temperature\": 35," +
"\"outlook\": \"Sunny\"" +
"}", Weather.class);
assertEquals("Lisbon", weather.getLocation());
assertEquals("Sunny", weather.getOutlook());
assertEquals(35, weather.getTemp());
}
}

View File

@@ -0,0 +1,40 @@
package com.baeldung.gson.deserialization;
import java.text.ParseException;
import com.baeldung.gson.entities.Movie;
import com.baeldung.gson.serialization.ActorGsonDeserializer;
import com.baeldung.gson.entities.ActorGson;
import org.junit.Assert;
import org.junit.Test;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class GsonDeserializeUnitTest {
@Test
public void whenSimpleDeserialize_thenCorrect() throws ParseException {
final String jsonInput = "{\"imdbId\":\"tt0472043\",\"actors\":" + "[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"Tue Sep 21 11:00:00 GMT 1982\",\"filmography\":" + "[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}";
final Gson gson = new GsonBuilder().setDateFormat("EEE MMM dd hh:mm:ss zzz yyyy").create();
final Movie outputMovie = gson.fromJson(jsonInput, Movie.class);
final String expectedOutput = "Movie [imdbId=tt0472043, director=null, actors=[ActorGson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 11:00:00 GMT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]";
Assert.assertEquals(outputMovie.toString(), expectedOutput);
}
@Test
public void whenCustomDeserialize_thenCorrect() throws ParseException {
final String jsonInput = "{\"imdbId\":\"tt0472043\",\"actors\":" + "[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"1982-09-21T12:00:00+01:00\",\"filmography\":" + "[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}";
final Gson gson = new GsonBuilder().registerTypeAdapter(ActorGson.class, new ActorGsonDeserializer()).create();
final Movie outputMovie = gson.fromJson(jsonInput, Movie.class);
final String expectedOutput = "Movie [imdbId=tt0472043, director=null, actors=[ActorGson [imdbId=nm2199632, dateOfBirth=Tue Sep 21 11:00:00 GMT 1982, filmography=[Apocalypto, Beatdown, Wind Walkers]]]]";
Assert.assertEquals(outputMovie.toString(), expectedOutput);
}
}

View File

@@ -0,0 +1,112 @@
package com.baeldung.gson.deserialization;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import org.apache.commons.lang3.time.DateUtils;
import com.baeldung.gson.entities.Employee;
import com.baeldung.gson.serialization.MapDeserializer;
import com.baeldung.gson.serialization.StringDateMapDeserializer;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
public class MapDeserializationUnitTest {
private static final Logger logger = LoggerFactory.getLogger(MapDeserializationUnitTest.class);
@Test
public void whenUsingMapClass_thenShouldReturnMapWithDefaultClasses() {
String jsonString = "{'employee.name':'Bob','employee.salary':10000, 'employee.active':true, "
+ "'employee':{'id':10, 'name': 'Bob Willis', 'address':'London'}}";
Gson gson = new Gson();
Map map = gson.fromJson(jsonString, Map.class);
logger.info("The converted map: {}", map);
Assert.assertEquals(4, map.size());
Assert.assertEquals(Double.class, map.get("employee.salary").getClass());
Assert.assertEquals(LinkedTreeMap.class, map.get("employee").getClass());
}
@Test(expected = JsonSyntaxException.class)
public void whenUsingJsonStringWithDuplicateKey_thenShouldThrowJsonSyntaxException() {
String jsonString = "{'employee.name':'Bob', 'employee.name':'Jenny','employee.salary':10000, "
+ "'employee.active':true, " + "'employee':{'id':10, 'name': 'Bob Willis', 'address':'London'}}";
Gson gson = new Gson();
Map map = gson.fromJson(jsonString, Map.class);
logger.info("The converted map: {}", map);
}
@Test
public void whenUsingTypeToken_thenShouldReturnMapWithProperClass() {
String jsonString = "{'Bob':{'id':10, 'name': 'Bob Willis', 'address':'UK'},"
+ "'Jenny':{'id':10, 'name': 'Jenny McCarthy', 'address':'USA'}, "
+ "'Steve':{'id':10, 'name': 'Steven Waugh', 'address':'Australia'}}";
Gson gson = new Gson();
Type empMapType = new TypeToken<Map<String, Employee>>(){}.getType();
Map<String, Employee> nameEmployeeMap = gson.fromJson(jsonString, empMapType);
logger.info("The converted map: {}", nameEmployeeMap);
Assert.assertEquals(3, nameEmployeeMap.size());
Assert.assertEquals(Employee.class, nameEmployeeMap.get("Bob").getClass());
}
@Test
public void whenUsingCustomDeserializer_thenShouldReturnMapWithProperClass() {
String jsonString = "{'employee.name':'Bob','employee.salary':10000, 'employee.active':true, "
+ "'employee':{'id':10, 'name': 'Bob Willis', 'address':'London'}}";
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Gson gson = new GsonBuilder()
.registerTypeAdapter(type, new MapDeserializer())
.create();
Map<String, Object> blendedMap = gson.fromJson(jsonString, type);
logger.info("The converted map: {}", blendedMap);
Assert.assertEquals(4, blendedMap.size());
Assert.assertEquals(Integer.class, blendedMap.get("employee.salary").getClass());
Assert.assertEquals(Employee.class, blendedMap.get("employee").getClass());
}
@Test
public void whenUsingCustomDateDeserializer_thenShouldReturnMapWithDate() {
String jsonString = "{'Bob': '2017/06/01', 'Jennie':'2015/01/03'}";
Type type = new TypeToken<Map<String, Date>>(){}.getType();
Gson gson = new GsonBuilder()
.registerTypeAdapter(type, new StringDateMapDeserializer())
.create();
Map<String, Date> empJoiningDateMap = gson.fromJson(jsonString, type);
logger.info("The converted map: {}", empJoiningDateMap);
logger.info("The map class {}", empJoiningDateMap.getClass());
Assert.assertEquals(2, empJoiningDateMap.size());
Assert.assertEquals(Date.class, empJoiningDateMap.get("Bob").getClass());
Date dt = null;
try {
dt = DateUtils.parseDate("2017-06-01", "yyyy-MM-dd");
Assert.assertEquals(dt, empJoiningDateMap.get("Bob"));
} catch (ParseException e) {
logger.error("Could not parse date", e);
}
}
}

View File

@@ -0,0 +1,138 @@
package com.baeldung.gson.deserialization.test;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import com.baeldung.gson.deserialization.Foo;
import com.baeldung.gson.deserialization.FooDeserializerFromJsonWithDifferentFields;
import com.baeldung.gson.deserialization.FooInstanceCreator;
import com.baeldung.gson.deserialization.FooWithInner;
import com.baeldung.gson.deserialization.GenericFoo;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
public class GsonDeserializationUnitTest {
// tests - single element
@Test
public final void whenDeserializingToSimpleObject_thenCorrect() {
final String json = "{\"intValue\":1,\"stringValue\":\"one\"}";
final Foo targetObject = new Gson().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
}
@Test
public final void givenJsonHasExtraValues_whenDeserializing_thenCorrect() {
final String json = "{\"intValue\":1,\"stringValue\":\"one\",\"extraString\":\"two\",\"extraFloat\":2.2}";
final Foo targetObject = new Gson().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
}
@Test
public final void givenJsonHasNonMatchingFields_whenDeserializingWithCustomDeserializer_thenCorrect() {
final String json = "{\"valueInt\":7,\"valueString\":\"seven\"}";
final GsonBuilder gsonBldr = new GsonBuilder();
gsonBldr.registerTypeAdapter(Foo.class, new FooDeserializerFromJsonWithDifferentFields());
final Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 7);
assertEquals(targetObject.stringValue, "seven");
}
@Test
public final void whenDeserializingToGenericObject_thenCorrect() {
final Type typeToken = new TypeToken<GenericFoo<Integer>>() {
}.getType();
final String json = "{\"theValue\":1}";
final GenericFoo<Integer> targetObject = new Gson().fromJson(json, typeToken);
assertEquals(targetObject.theValue, new Integer(1));
}
// tests - multiple elements
@Test
public final void givenJsonArrayOfFoos_whenDeserializingToArray_thenCorrect() {
final String json = "[{\"intValue\":1,\"stringValue\":\"one\"}," + "{\"intValue\":2,\"stringValue\":\"two\"}]";
final Foo[] targetArray = new GsonBuilder().create().fromJson(json, Foo[].class);
assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(1, "one")));
assertThat(Lists.newArrayList(targetArray), hasItem(new Foo(2, "two")));
assertThat(Lists.newArrayList(targetArray), not(hasItem(new Foo(1, "two"))));
}
@Test
public final void givenJsonArrayOfFoos_whenDeserializingCollection_thenCorrect() {
final String json = "[{\"intValue\":1,\"stringValue\":\"one\"},{\"intValue\":2,\"stringValue\":\"two\"}]";
final Type targetClassType = new TypeToken<ArrayList<Foo>>() {
}.getType();
final Collection<Foo> targetCollection = new Gson().fromJson(json, targetClassType);
assertThat(targetCollection, instanceOf(ArrayList.class));
}
//
@Test
public void whenDeserializingJsonIntoElements_thenCorrect() {
final String jsonSourceObject = "{\"valueInt\":7,\"valueString\":\"seven\"}";
final JsonParser jParser = new JsonParser();
final JsonElement jElement = jParser.parse(jsonSourceObject);
final JsonObject jObject = jElement.getAsJsonObject();
final int intValue = jObject.get("valueInt").getAsInt();
final String stringValue = jObject.get("valueString").getAsString();
final Foo targetObject = new Foo(intValue, stringValue);
assertEquals(targetObject.intValue, 7);
assertEquals(targetObject.stringValue, "seven");
}
// new examples
@Test
public void whenDeserializingToNestedObjects_thenCorrect() {
final String json = "{\"intValue\":1,\"stringValue\":\"one\",\"innerFoo\":{\"name\":\"inner\"}}";
final FooWithInner targetObject = new Gson().fromJson(json, FooWithInner.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "one");
assertEquals(targetObject.innerFoo.name, "inner");
}
@Test
public void whenDeserializingUsingInstanceCreator_thenCorrect() {
final String json = "{\"intValue\":1}";
final GsonBuilder gsonBldr = new GsonBuilder();
gsonBldr.registerTypeAdapter(Foo.class, new FooInstanceCreator());
final Foo targetObject = gsonBldr.create().fromJson(json, Foo.class);
assertEquals(targetObject.intValue, 1);
assertEquals(targetObject.stringValue, "sample");
}
}

View File

@@ -0,0 +1,95 @@
package com.baeldung.gson.jsoncompare;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.junit.Test;
import static org.junit.Assert.*;
public class JsonCompareUnitTest {
@Test
public void givenJsonStrings_whenCompared_thenNotEqual() {
String string1 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27 }";
String string2 = "{\"fullName\": \"Emily Jenkins\", \"age\": 27}";
assertNotEquals(string1, string2);
}
@Test
public void givenIdenticalSimpleObjects_whenCompared_thenEqual() {
JsonParser parser = new JsonParser();
String string1 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27 }}";
String string2 = "{\"customer\": {\"id\": \"44521\", \"fullName\": \"Emily Jenkins\",\"age\": 27}}";
assertTrue(parser.parse(string1)
.isJsonObject());
assertEquals(parser.parse(string1), parser.parse(string2));
}
@Test
public void givenSameObjectsInDifferentOrder_whenCompared_thenEqual() {
JsonParser parser = new JsonParser();
String string1 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27 }}";
String string2 = "{\"customer\": {\"id\": \"44521\",\"age\": 27, \"fullName\": \"Emily Jenkins\" }}";
JsonElement json1 = parser.parse(string1);
JsonElement json2 = parser.parse(string2);
assertEquals(json1, json2);
}
@Test
public void givenIdenticalArrays_whenCompared_thenEqual() {
JsonParser parser = new JsonParser();
String string1 = "[10, 20, 30]";
String string2 = "[10, 20, 30]";
assertTrue(parser.parse(string1)
.isJsonArray());
assertEquals(parser.parse(string1), parser.parse(string2));
}
@Test
public void givenArraysInDifferentOrder_whenCompared_thenNotEqual() {
JsonParser parser = new JsonParser();
String string1 = "[20, 10, 30]";
String string2 = "[10, 20, 30]";
assertNotEquals(parser.parse(string1), parser.parse(string2));
}
@Test
public void givenIdenticalNestedObjects_whenCompared_thenEqual() {
JsonParser parser = new JsonParser();
String string1 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27, \"consumption_info\" : {\"fav_product\": \"Coke\", \"last_buy\": \"2012-04-23\"}}}";
String string2 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27, \"consumption_info\" : {\"last_buy\": \"2012-04-23\", \"fav_product\": \"Coke\"}}}";
JsonElement json1 = parser.parse(string1);
JsonElement json2 = parser.parse(string2);
assertEquals(json1, json2);
}
@Test
public void givenIdenticalNestedObjectsWithArray_whenCompared_thenEqual() {
JsonParser parser = new JsonParser();
String string1 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27, \"consumption_info\" : {\"last_buy\": \"2012-04-23\", \"prouducts\": [\"banana\", \"eggs\"]}}}";
String string2 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27, \"consumption_info\" : {\"last_buy\": \"2012-04-23\", \"prouducts\": [\"banana\", \"eggs\"]}}}";
JsonElement json1 = parser.parse(string1);
JsonElement json2 = parser.parse(string2);
assertEquals(json1, json2);
}
@Test
public void givenNestedObjectsDifferentArrayOrder_whenCompared_thenNotEqual() {
JsonParser parser = new JsonParser();
String string1 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27, \"consumption_info\" : {\"last_buy\": \"2012-04-23\", \"prouducts\": [\"banana\", \"eggs\"]}}}";
String string2 = "{\"customer\": {\"id\": \"44521\",\"fullName\": \"Emily Jenkins\", \"age\": 27, \"consumption_info\" : {\"last_buy\": \"2012-04-23\", \"prouducts\": [\"eggs\", \"banana\"]}}}";
JsonElement json1 = parser.parse(string1);
JsonElement json2 = parser.parse(string2);
assertNotEquals(json1, json2);
}
}

View File

@@ -0,0 +1,248 @@
package com.baeldung.gson.primitives;
import com.baeldung.gson.primitives.models.*;
import com.google.gson.*;
import org.junit.Test;
import java.lang.reflect.Type;
import static junit.framework.TestCase.*;
public class PrimitiveValuesUnitTest {
@Test public void whenSerializingToJSON_thenShouldCreateJSON() {
PrimitiveBundle primitiveBundle = new PrimitiveBundle();
// @formatter:off
primitiveBundle.byteValue = (byte) 0x00001111;
primitiveBundle.shortValue = (short) 3;
primitiveBundle.intValue = 3;
primitiveBundle.longValue = 3;
primitiveBundle.floatValue = 3.5f;
primitiveBundle.doubleValue = 3.5;
primitiveBundle.booleanValue = true;
primitiveBundle.charValue = 'a';
// @formatter:on
Gson gson = new Gson();
String expected = "{\"byteValue\":17,\"shortValue\":3,\"intValue\":3,"
+ "\"longValue\":3,\"floatValue\":3.5" + ",\"doubleValue\":3.5"
+ ",\"booleanValue\":true,\"charValue\":\"a\"}";
assertEquals(expected, gson.toJson(primitiveBundle));
}
@Test(expected = IllegalArgumentException.class) public void
whenSerializingInfinity_thenShouldRaiseAnException() {
InfinityValuesExample model = new InfinityValuesExample();
model.negativeInfinity = Float.NEGATIVE_INFINITY;
model.positiveInfinity = Float.POSITIVE_INFINITY;
Gson gson = new Gson();
gson.toJson(model);
}
@Test(expected = IllegalArgumentException.class) public void
whenSerializingNaN_thenShouldRaiseAnException() {
FloatExample model = new FloatExample();
model.value = Float.NaN;
Gson gson = new Gson();
gson.toJson(model);
}
@Test public void whenDeserializingFromJSON_thenShouldParseTheValueInTheString() {
String json = "{\"byteValue\": 17, \"shortValue\": 3, \"intValue\": 3, "
+ "\"longValue\": 3, \"floatValue\": 3.5" + ", \"doubleValue\": 3.5"
+ ", \"booleanValue\": true, \"charValue\": \"a\"}";
Gson gson = new Gson();
PrimitiveBundle model = gson.fromJson(json, PrimitiveBundle.class);
// @formatter:off
assertEquals(17, model.byteValue);
assertEquals(3, model.shortValue);
assertEquals(3, model.intValue);
assertEquals(3, model.longValue);
assertEquals(3.5, model.floatValue, 0.0001);
assertEquals(3.5, model.doubleValue, 0.0001);
assertTrue( model.booleanValue);
assertEquals('a', model.charValue);
// @formatter:on
}
@Test public void whenDeserializingHighPrecissionNumberIntoFloat_thenShouldPerformRounding() {
String json = "{\"value\": 12.123425589123456}";
Gson gson = new Gson();
FloatExample model = gson.fromJson(json, FloatExample.class);
assertEquals(12.123426f, model.value, 0.000001);
}
@Test public void whenDeserializingHighPrecissiongNumberIntoDouble_thenShouldPerformRounding() {
String json = "{\"value\": 12.123425589123556}";
Gson gson = new Gson();
DoubleExample model = gson.fromJson(json, DoubleExample.class);
assertEquals(12.123425589124f, model.value, 0.000001);
}
@Test public void whenDeserializingValueThatOverflows_thenShouldOverflowSilently() {
Gson gson = new Gson();
String json = "{\"value\": \"300\"}";
ByteExample model = gson.fromJson(json, ByteExample.class);
assertEquals(44, model.value);
}
@Test public void whenDeserializingRealIntoByte_thenShouldRaiseAnException() {
Gson gson = new Gson();
String json = "{\"value\": 2.3}";
try {
gson.fromJson(json, ByteExample.class);
} catch (Exception ex) {
assertTrue(ex instanceof JsonSyntaxException);
assertTrue(ex.getCause() instanceof NumberFormatException);
return;
}
fail();
}
@Test public void whenDeserializingRealIntoLong_thenShouldRaiseAnException() {
Gson gson = new Gson();
String json = "{\"value\": 2.3}";
try {
gson.fromJson(json, LongExample.class);
} catch (Exception ex) {
assertTrue(ex instanceof JsonSyntaxException);
assertTrue(ex.getCause() instanceof NumberFormatException);
return;
}
fail();
}
@Test public void whenDeserializingRealWhoseDecimalPartIs0_thenShouldParseItCorrectly() {
Gson gson = new Gson();
String json = "{\"value\": 2.0}";
LongExample model = gson.fromJson(json, LongExample.class);
assertEquals(2, model.value);
}
@Test public void whenDeserializingUnicodeChar_thenShouldParseItCorrectly() {
Gson gson = new Gson();
String json = "{\"value\": \"\\u00AE\"}";
CharExample model = gson.fromJson(json, CharExample.class);
assertEquals('\u00AE', model.value);
}
@Test public void whenDeserializingNullValues_thenShouldIgnoreThoseFields() {
Gson gson = new Gson();
// @formatter:off
String json = "{\"byteValue\": null, \"shortValue\": null, "
+ "\"intValue\": null, " + "\"longValue\": null, \"floatValue\": null"
+ ", \"doubleValue\": null}";
// @formatter:on
PrimitiveBundleInitialized model = gson.fromJson(json,
PrimitiveBundleInitialized.class);
assertEquals(1, model.byteValue);
assertEquals(1, model.shortValue);
assertEquals(1, model.intValue);
assertEquals(1, model.longValue);
assertEquals(1, model.floatValue, 0.0001);
assertEquals(1, model.doubleValue, 0.0001);
}
@Test(expected = JsonSyntaxException.class) public void
whenDeserializingTheEmptyString_thenShouldRaiseAnException() {
Gson gson = new Gson();
// @formatter:off
String json = "{\"byteValue\": \"\", \"shortValue\": \"\", "
+ "\"intValue\": \"\", " + "\"longValue\": \"\", \"floatValue\": \"\""
+ ", \"doubleValue\": \"\"" + ", \"booleanValue\": \"\"}";
// @formatter:on
gson.fromJson(json, PrimitiveBundleInitialized.class);
}
@Test public void whenDeserializingTheEmptyStringIntoChar_thenShouldHaveTheEmtpyChar() {
Gson gson = new Gson();
// @formatter:off
String json = "{\"charValue\": \"\"}";
// @formatter:on
CharExample model = gson.fromJson(json, CharExample.class);
assertEquals(Character.MIN_VALUE, model.value);
}
@Test public void whenDeserializingValidValueAppearingInAString_thenShouldParseTheValue() {
Gson gson = new Gson();
// @formatter:off
String json = "{\"byteValue\": \"15\", \"shortValue\": \"15\", "
+ "\"intValue\": \"15\", " + "\"longValue\": \"15\", \"floatValue\": \"15.0\""
+ ", \"doubleValue\": \"15.0\"}";
// @formatter:on
PrimitiveBundleInitialized model = gson.fromJson(json,
PrimitiveBundleInitialized.class);
assertEquals(15, model.byteValue);
assertEquals(15, model.shortValue);
assertEquals(15, model.intValue);
assertEquals(15, model.longValue);
assertEquals(15, model.floatValue, 0.0001);
assertEquals(15, model.doubleValue, 0.0001);
}
@Test public void whenDeserializingABooleanFrom0Or1Integer_thenShouldRaiseAnException() {
String json = "{\"value\": 1}";
Gson gson = new Gson();
try {
gson.fromJson(json, BooleanExample.class);
} catch (Exception ex) {
assertTrue(ex instanceof JsonSyntaxException);
assertTrue(ex.getCause() instanceof IllegalStateException);
return;
}
fail();
}
@Test public void whenDeserializingWithCustomDeserializerABooleanFrom0Or1Integer_thenShouldWork() {
String json = "{\"value\": 1}";
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(BooleanExample.class,
new BooleanAs2ValueIntegerDeserializer());
Gson gson = builder.create();
BooleanExample model = gson.fromJson(json, BooleanExample.class);
assertTrue(model.value);
}
// @formatter:off
static class BooleanAs2ValueIntegerDeserializer implements JsonDeserializer<BooleanExample> {
@Override public BooleanExample deserialize(
JsonElement jsonElement,
Type type,
JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
BooleanExample model = new BooleanExample();
int value = jsonElement.getAsJsonObject().getAsJsonPrimitive("value").getAsInt();
if (value == 0) {
model.value = false;
} else if (value == 1) {
model.value = true;
} else {
throw new JsonParseException("Unexpected value. Trying to deserialize "
+ "a boolean from an integer different than 0 and 1.");
}
return model;
}
}
// @formatter:on
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.gson.serialization;
import java.lang.reflect.Type;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public class DifferentNameSerializer implements JsonSerializer<SourceClass> {
@Override
public JsonElement serialize(final SourceClass src, final Type typeOfSrc, final JsonSerializationContext context) {
final String otherIntValueName = "otherIntValue";
final String otherStringValueName = "otherStringValue";
final JsonObject jObject = new JsonObject();
jObject.addProperty(otherIntValueName, src.getIntValue());
jObject.addProperty(otherStringValueName, src.getStringValue());
return jObject;
}
}

View File

@@ -0,0 +1,48 @@
package com.baeldung.gson.serialization;
import com.baeldung.gson.entities.Movie;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParser;
import com.baeldung.gson.entities.ActorGson;
import com.baeldung.gson.entities.MovieWithNullValue;
import org.junit.Assert;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
public class GsonSerializeUnitTest {
@Test
public void whenSimpleSerialize_thenCorrect() throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
ActorGson rudyYoungblood = new ActorGson("nm2199632", sdf.parse("21-09-1982"), Arrays.asList("Apocalypto", "Beatdown", "Wind Walkers"));
Movie movie = new Movie("tt0472043", "Mel Gibson", Arrays.asList(rudyYoungblood));
String expectedOutput = "{\"imdbId\":\"tt0472043\",\"director\":\"Mel Gibson\",\"actors\":[{\"imdbId\":\"nm2199632\",\"dateOfBirth\":\"Sep 21, 1982 12:00:00 AM\",\"filmography\":[\"Apocalypto\",\"Beatdown\",\"Wind Walkers\"]}]}";
Assert.assertEquals(new Gson().toJson(movie), expectedOutput);
}
@Test
public void whenCustomSerialize_thenCorrect() throws ParseException {
Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().serializeNulls().disableHtmlEscaping().registerTypeAdapter(ActorGson.class, new ActorGsonSerializer()).create();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
ActorGson rudyYoungblood = new ActorGson("nm2199632", sdf.parse("21-09-1982"), Arrays.asList("Apocalypto", "Beatdown", "Wind Walkers"));
MovieWithNullValue movieWithNullValue = new MovieWithNullValue(null, "Mel Gibson", Arrays.asList(rudyYoungblood));
String expectedOutput = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.disableHtmlEscaping()
.create()
.toJson(new JsonParser()
.parse("{\"imdbId\":null,\"actors\":[{\"<strong>IMDB Code</strong>\":\"nm2199632\",\"<strong>Date Of Birth</strong>\":\"21-09-1982\",\"<strong>N° Film:</strong> \":3,\"filmography\":\"Apocalypto-Beatdown-Wind Walkers\"}]}"));
Assert.assertEquals(gson.toJson(movieWithNullValue), expectedOutput);
}
}

View File

@@ -0,0 +1,27 @@
package com.baeldung.gson.serialization;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
public class IgnoringFieldsNotMatchingCriteriaSerializer implements JsonSerializer<SourceClass> {
@Override
public JsonElement serialize(SourceClass src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jObject = new JsonObject();
// Criteria: intValue >= 0
if (src.getIntValue() >= 0) {
String intValue = "intValue";
jObject.addProperty(intValue, src.getIntValue());
}
String stringValue = "stringValue";
jObject.addProperty(stringValue, src.getStringValue());
return jObject;
}
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.gson.serialization;
import java.lang.reflect.Type;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
public class IgnoringFieldsSerializer implements JsonSerializer<SourceClass> {
@Override
public JsonElement serialize(final SourceClass src, final Type typeOfSrc, final JsonSerializationContext context) {
final String intValue = "intValue";
final JsonObject jObject = new JsonObject();
jObject.addProperty(intValue, src.getIntValue());
return jObject;
}
}

View File

@@ -0,0 +1,52 @@
package com.baeldung.gson.serialization;
public class SourceClass {
private int intValue;
private String stringValue;
public SourceClass(final int intValue, final String stringValue) {
this.intValue = intValue;
this.stringValue = stringValue;
}
// API
public int getIntValue() {
return intValue;
}
public String getStringValue() {
return stringValue;
}
//
@Override
public String toString() {
return "SourceClass{" + "intValue=" + intValue + ", stringValue='" + stringValue + '\'' + '}';
}
@Override
public boolean equals(final Object o) {
if (this == o)
return true;
if (!(o instanceof SourceClass))
return false;
final SourceClass that = (SourceClass) o;
if (intValue != that.intValue)
return false;
if (!stringValue.equals(that.stringValue))
return false;
return true;
}
@Override
public int hashCode() {
int result = intValue;
result = 31 * result + stringValue.hashCode();
return result;
}
}

View File

@@ -0,0 +1,95 @@
package com.baeldung.gson.serialization.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Date;
import com.baeldung.gson.serialization.DifferentNameSerializer;
import com.baeldung.gson.serialization.IgnoringFieldsNotMatchingCriteriaSerializer;
import com.baeldung.gson.serialization.IgnoringFieldsSerializer;
import com.baeldung.gson.serialization.SourceClass;
import org.assertj.core.util.Lists;
import org.joda.time.DateTime;
import org.junit.Test;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
public class GsonSerializationUnitTest {
@Test
public void givenArrayOfObjects_whenSerializing_thenCorrect() {
final SourceClass[] sourceArray = { new SourceClass(1, "one"), new SourceClass(2, "two") };
final String jsonString = new Gson().toJson(sourceArray);
// test
final String expectedResult = "[{\"intValue\":1,\"stringValue\":\"one\"},{\"intValue\":2,\"stringValue\":\"two\"}]";
assertEquals(expectedResult, jsonString);
}
@Test
public void givenCollection_whenSerializing_thenCorrect() {
final Collection<SourceClass> sourceCollection = Lists.newArrayList(new SourceClass(1, "one"), new SourceClass(2, "two"));
final String jsonCollection = new Gson().toJson(sourceCollection);
final String expectedResult = "[{\"intValue\":1,\"stringValue\":\"one\"},{\"intValue\":2,\"stringValue\":\"two\"}]";
assertEquals(expectedResult, jsonCollection);
}
@Test
public void givenUsingCustomSerializer_whenChangingNameOfFieldOnSerializing_thenCorrect() {
final SourceClass sourceObject = new SourceClass(7, "seven");
final GsonBuilder gsonBuildr = new GsonBuilder();
gsonBuildr.registerTypeAdapter(SourceClass.class, new DifferentNameSerializer());
final String jsonString = gsonBuildr.create().toJson(sourceObject);
final String expectedResult = "{\"otherIntValue\":7,\"otherStringValue\":\"seven\"}";
assertEquals(expectedResult, jsonString);
}
@Test
public void givenIgnoringAField_whenSerializingWithCustomSerializer_thenFieldIgnored() {
final SourceClass sourceObject = new SourceClass(7, "seven");
final GsonBuilder gsonBuildr = new GsonBuilder();
gsonBuildr.registerTypeAdapter(SourceClass.class, new IgnoringFieldsSerializer());
final String jsonString = gsonBuildr.create().toJson(sourceObject);
final String expectedResult = "{\"intValue\":7}";
assertEquals(expectedResult, jsonString);
}
@Test
public void givenUsingCustomDeserializer_whenFieldNotMatchesCriteria_thenIgnored() {
final SourceClass sourceObject = new SourceClass(-1, "minus 1");
final GsonBuilder gsonBuildr = new GsonBuilder();
gsonBuildr.registerTypeAdapter(SourceClass.class, new IgnoringFieldsNotMatchingCriteriaSerializer());
final Gson gson = gsonBuildr.create();
final Type sourceObjectType = new TypeToken<SourceClass>() {
}.getType();
final String jsonString = gson.toJson(sourceObject, sourceObjectType);
final String expectedResult = "{\"stringValue\":\"minus 1\"}";
assertEquals(expectedResult, jsonString);
}
@Test
public void givenDate_whenSerializing_thenCorrect() {
Date sourceDate = new DateTime().withYear(2000).withMonthOfYear(1).withDayOfMonth(1).withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).toDate();
final Gson gson = new Gson();
Type sourceDateType = new TypeToken<Date>() {
}.getType();
String jsonDate = gson.toJson(sourceDate, sourceDateType);
System.out.println("jsonDate:\n" + jsonDate);
String expectedResult = "\"Jan 1, 2000 12:00:00 AM\"";
assertEquals(expectedResult, jsonDate);
}
}

View File

@@ -0,0 +1,43 @@
package com.baeldung.gson.serialization.test;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Paths;
import com.baeldung.gson.entities.User;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
@RunWith(Parameterized.class)
public class JsonFileUnitTest {
@Parameter
public Object object;
@Parameters
public static Object[] data() {
return new Object[] { 123.45, new User(1, "Tom", "American") };
}
@Test
public void givenProperData_whenStoredInFile_shouldSaveJsonSuccessfully() {
String filePath = "target/output.json";
try (Writer writer = new FileWriter(filePath)) {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
gson.toJson(object, writer);
Assert.assertTrue(Files.exists(Paths.get(filePath)));
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,104 @@
package com.baeldung.gson.serializationwithexclusions;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
class SerializationWithExclusionsUnitTest {
final String expectedResult = "{\"id\":1,\"name\":\"foo\",\"subclass\":{\"id\":42,\"description\":\"the answer\"}}";
@Test
public void givenClassWithTransientFields_whenSerializing_thenCorrectWithoutTransientFields() {
MyClassWithTransientFields source = new MyClassWithTransientFields(1L, "foo", "bar", new MySubClassWithTransientFields(42L, "the answer", "Verbose field which we don't want to be serialized"));
String jsonString = new Gson().toJson(source);
assertEquals(expectedResult, jsonString);
}
@Test
public void givenClassAnnotated_whenSerializing_thenCorrectWithoutNotAnnotatedFields() {
MyClassWithAnnotatedFields source = new MyClassWithAnnotatedFields(1L, "foo", "bar", new MySubClassWithAnnotatedFields(42L, "the answer", "Verbose field which we don't want to be serialized"));
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
.create();
String jsonString = gson.toJson(source);
assertEquals(expectedResult, jsonString);
}
@Test
public void givenExclusionStrategyByClassesAndFields_whenSerializing_thenFollowStrategy() {
MyClass source = new MyClass(1L, "foo", "bar", new MySubClass(42L, "the answer", "Verbose field which we don't want to be serialized"));
ExclusionStrategy strategy = new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes field) {
if (field.getDeclaringClass() == MyClass.class && field.getName()
.equals("other"))
return true;
if (field.getDeclaringClass() == MySubClass.class && field.getName()
.equals("otherVerboseInfo"))
return true;
return false;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
};
Gson gson = new GsonBuilder().addSerializationExclusionStrategy(strategy)
.create();
String jsonString = gson.toJson(source);
assertEquals(expectedResult, jsonString);
}
@Test
public void givenExclusionStrategyByStartsWith_whenSerializing_thenFollowStrategy() {
MyClass source = new MyClass(1L, "foo", "bar", new MySubClass(42L, "the answer", "Verbose field which we don't want to be serialized"));
ExclusionStrategy strategy = new ExclusionStrategy() {
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
@Override
public boolean shouldSkipField(FieldAttributes field) {
return field.getName().startsWith("other");
}
};
Gson gson = new GsonBuilder().setExclusionStrategies(strategy)
.create();
String jsonString = gson.toJson(source);
assertEquals(expectedResult, jsonString);
}
@Test
public void givenExclusionStrategyByCustomAnnotation_whenSerializing_thenFollowStrategy() {
MyClassWithCustomAnnotatedFields source = new MyClassWithCustomAnnotatedFields(1L, "foo", "bar", new MySubClassWithCustomAnnotatedFields(42L, "the answer", "Verbose field which we don't want to be serialized"));
ExclusionStrategy strategy = new ExclusionStrategy() {
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
@Override
public boolean shouldSkipField(FieldAttributes field) {
return field.getAnnotation(Exclude.class) != null;
}
};
Gson gson = new GsonBuilder().setExclusionStrategies(strategy)
.create();
String jsonString = gson.toJson(source);
assertEquals(expectedResult, jsonString);
}
}

View File

@@ -0,0 +1,13 @@
*.class
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
# Packaged files #
*.jar
*.war
*.ear

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN"/>
<logger name="org.springframework.transaction" level="WARN"/>
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN"/>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@@ -0,0 +1,13 @@
## JSON
This module contains articles about JSON.
### Relevant Articles:
- [Introduction to Jsoniter](https://www.baeldung.com/java-jsoniter)
- [Introduction to Moshi Json](https://www.baeldung.com/java-json-moshi)
- [Hypermedia Serialization With JSON-LD](https://www.baeldung.com/json-linked-data)
- [Generate a Java Class From JSON](https://www.baeldung.com/java-generate-class-from-json)
- [A Guide to FastJson](https://www.baeldung.com/fastjson)
- [Check Whether a String is Valid JSON in Java](https://www.baeldung.com/java-validate-json-string)
- More Articles: [[<-- prev]](/json)

163
json-modules/json-2/pom.xml Normal file
View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>json-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>json-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>${json.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.jsonschema2pojo</groupId>
<artifactId>jsonschema2pojo-core</artifactId>
<version>${jsonschema2pojo-core.version}</version>
</dependency>
<dependency>
<groupId>com.jsoniter</groupId>
<artifactId>jsoniter</artifactId>
<version>${jsoniter.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi</artifactId>
<version>${moshi.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-adapters</artifactId>
<version>${moshi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.io-informatics.oss</groupId>
<artifactId>jackson-jsonld</artifactId>
<version>${jackson-jsonld.version}</version>
<exclusions>
<exclusion>
<artifactId>jackson-databind</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
<exclusion>
<artifactId>jackson-annotations</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
<exclusion>
<artifactId>jackson-core</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
<exclusion>
<artifactId>jsonld-java</artifactId>
<groupId>com.github.jsonld-java</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>de.escalon.hypermedia</groupId>
<artifactId>hydra-jsonld</artifactId>
<version>${hydra-jsonld.version}</version>
<exclusions>
<exclusion>
<artifactId>jackson-databind</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.jsonld-java</groupId>
<artifactId>jsonld-java</artifactId>
<version>${jsonld-java.version}</version>
<exclusions>
<exclusion>
<artifactId>jackson-core</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
<exclusion>
<artifactId>jackson-databind</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no
influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-pmd-plugin
</artifactId>
<versionRange>
[3.13.0,)
</versionRange>
<goals>
<goal>check</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<jsoniter.version>0.9.23</jsoniter.version>
<moshi.version>1.9.2</moshi.version>
<fastjson.version>1.2.21</fastjson.version>
<json.version>20211205</json.version>
<jsonschema2pojo-core.version>1.1.1</jsonschema2pojo-core.version>
<jackson-jsonld.version>0.1.1</jackson-jsonld.version>
<hydra-jsonld.version>0.4.2</hydra-jsonld.version>
<jsonld-java.version>0.13.0</jsonld-java.version>
</properties>
</project>

View File

@@ -0,0 +1,22 @@
package com.baeldung.jsoniter.model;
public class Name {
private String firstName;
private String surname;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}

View File

@@ -0,0 +1,26 @@
package com.baeldung.jsoniter.model;
import com.jsoniter.annotation.JsonProperty;
import com.jsoniter.fuzzy.MaybeStringIntDecoder;
public class Student {
@JsonProperty(decoder = MaybeStringIntDecoder.class)
private int id;
private Name name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
}

View File

@@ -0,0 +1,123 @@
package com.baeldung.jsonoptimization;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Customer {
private long id;
private String firstName;
private String lastName;
private String street;
private String postalCode;
private String city;
private String state;
private String phoneNumber;
private String email;
public long getId() {
return id;
}
public void setId(long 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 String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public int hashCode() {
return Objects.hash(city, email, firstName, id, lastName, phoneNumber, postalCode, state, street);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Customer)) {
return false;
}
Customer other = (Customer) obj;
return Objects.equals(city, other.city) && Objects.equals(email, other.email) && Objects.equals(firstName, other.firstName) && id == other.id && Objects.equals(lastName, other.lastName) && Objects.equals(phoneNumber, other.phoneNumber)
&& Objects.equals(postalCode, other.postalCode) && Objects.equals(state, other.state) && Objects.equals(street, other.street);
}
@Override
public String toString() {
return "Customer [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", street=" + street + ", postalCode=" + postalCode + ", city=" + city + ", state=" + state + ", phoneNumber=" + phoneNumber + ", email=" + email + "]";
}
public static Customer[] fromMockFile() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
InputStream jsonFile = new FileInputStream("src/test/resources/json_optimization_mock_data.json");
Customer[] feedback = objectMapper.readValue(jsonFile, Customer[].class);
return feedback;
}
}

View File

@@ -0,0 +1,49 @@
package com.baeldung.jsonoptimization;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
public class CustomerDeserializer extends StdDeserializer<Customer> {
private static final long serialVersionUID = 1L;
public CustomerDeserializer() {
this(null);
}
public CustomerDeserializer(Class<Customer> t) {
super(t);
}
@Override
public Customer deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {
Customer feedback = new Customer();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
feedback.setId(node.get(0)
.asLong());
feedback.setFirstName(node.get(1)
.asText());
feedback.setLastName(node.get(2)
.asText());
feedback.setStreet(node.get(3)
.asText());
feedback.setPostalCode(node.get(4)
.asText());
feedback.setCity(node.get(5)
.asText());
feedback.setState(node.get(6)
.asText());
JsonNode phoneNumber = node.get(7);
feedback.setPhoneNumber(phoneNumber.isNull() ? null : phoneNumber.asText());
JsonNode email = node.get(8);
feedback.setEmail(email.isNull() ? null : email.asText());
return feedback;
}
}

View File

@@ -0,0 +1,34 @@
package com.baeldung.jsonoptimization;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class CustomerSerializer extends StdSerializer<Customer> {
private static final long serialVersionUID = 1L;
public CustomerSerializer() {
this(null);
}
public CustomerSerializer(Class<Customer> t) {
super(t);
}
@Override
public void serialize(Customer customer, JsonGenerator jsonGenerator, SerializerProvider serializer) throws IOException {
jsonGenerator.writeStartArray();
jsonGenerator.writeNumber(customer.getId());
jsonGenerator.writeString(customer.getFirstName());
jsonGenerator.writeString(customer.getLastName());
jsonGenerator.writeString(customer.getStreet());
jsonGenerator.writeString(customer.getPostalCode());
jsonGenerator.writeString(customer.getCity());
jsonGenerator.writeString(customer.getState());
jsonGenerator.writeString(customer.getPhoneNumber());
jsonGenerator.writeString(customer.getEmail());
jsonGenerator.writeEndArray();
}
}

View File

@@ -0,0 +1,155 @@
package com.baeldung.jsonoptimization;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
public class CustomerShortNames {
@JsonProperty("i")
private long id;
@JsonProperty("f")
private String firstName;
@JsonProperty("l")
private String lastName;
@JsonProperty("s")
private String street;
@JsonProperty("p")
private String postalCode;
@JsonProperty("c")
private String city;
@JsonProperty("a")
private String state;
@JsonProperty("o")
private String phoneNumber;
@JsonProperty("e")
private String email;
public long getId() {
return id;
}
public void setId(long 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 String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public int hashCode() {
return Objects.hash(city, email, firstName, id, lastName, phoneNumber, postalCode, state, street);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CustomerShortNames)) {
return false;
}
CustomerShortNames other = (CustomerShortNames) obj;
return Objects.equals(city, other.city) && Objects.equals(email, other.email) && Objects.equals(firstName, other.firstName) && id == other.id && Objects.equals(lastName, other.lastName) && Objects.equals(phoneNumber, other.phoneNumber)
&& Objects.equals(postalCode, other.postalCode) && Objects.equals(state, other.state) && Objects.equals(street, other.street);
}
@Override
public String toString() {
return "CustomerWithShorterAttributes [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", street=" + street + ", postalCode=" + postalCode + ", city=" + city + ", state=" + state + ", phoneNumber=" + phoneNumber + ", email=" + email
+ "]";
}
public static CustomerShortNames[] fromCustomers(Customer[] customers) {
CustomerShortNames[] feedback = new CustomerShortNames[customers.length];
for (int i = 0; i < customers.length; i++) {
Customer aCustomer = customers[i];
CustomerShortNames newOne = new CustomerShortNames();
newOne.setId(aCustomer.getId());
newOne.setFirstName(aCustomer.getFirstName());
newOne.setLastName(aCustomer.getLastName());
newOne.setStreet(aCustomer.getStreet());
newOne.setCity(aCustomer.getCity());
newOne.setPostalCode(aCustomer.getPostalCode());
newOne.setState(aCustomer.getState());
newOne.setPhoneNumber(aCustomer.getPhoneNumber());
newOne.setEmail(aCustomer.getEmail());
feedback[i] = newOne;
}
return feedback;
}
}

View File

@@ -0,0 +1,73 @@
package com.baeldung.jsonoptimization;
import java.util.Objects;
public class CustomerSlim {
private long id;
private String name;
private String address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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;
}
@Override
public int hashCode() {
return Objects.hash(address, id, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CustomerSlim)) {
return false;
}
CustomerSlim other = (CustomerSlim) obj;
return Objects.equals(address, other.address) && id == other.id && Objects.equals(name, other.name);
}
@Override
public String toString() {
return "CustomerSlim [id=" + id + ", name=" + name + ", address=" + address + "]";
}
public static CustomerSlim[] fromCustomers(Customer[] customers) {
CustomerSlim[] feedback = new CustomerSlim[customers.length];
for (int i = 0; i < customers.length; i++) {
Customer aCustomer = customers[i];
CustomerSlim newOne = new CustomerSlim();
newOne.setId(aCustomer.getId());
newOne.setName(aCustomer.getFirstName() + " " + aCustomer.getLastName());
newOne.setAddress(aCustomer.getStreet() + ", " + aCustomer.getCity() + " " + aCustomer.getState() + " " + aCustomer.getPostalCode());
feedback[i] = newOne;
}
return feedback;
}
}

View File

@@ -0,0 +1,37 @@
package com.baeldung.jsonoptimization;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
public class CustomerSlimDeserializer extends StdDeserializer<CustomerSlim> {
private static final long serialVersionUID = 1L;
public CustomerSlimDeserializer() {
this(null);
}
public CustomerSlimDeserializer(Class<CustomerSlim> t) {
super(t);
}
@Override
public CustomerSlim deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {
CustomerSlim feedback = new CustomerSlim();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
feedback.setId(node.get(0)
.asLong());
feedback.setName(node.get(1)
.asText());
feedback.setAddress(node.get(2)
.asText());
return feedback;
}
}

View File

@@ -0,0 +1,28 @@
package com.baeldung.jsonoptimization;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class CustomerSlimSerializer extends StdSerializer<CustomerSlim> {
private static final long serialVersionUID = 1L;
public CustomerSlimSerializer() {
this(null);
}
public CustomerSlimSerializer(Class<CustomerSlim> t) {
super(t);
}
@Override
public void serialize(CustomerSlim customer, JsonGenerator jsonGenerator, SerializerProvider serializer) throws IOException {
jsonGenerator.writeStartArray();
jsonGenerator.writeNumber(customer.getId());
jsonGenerator.writeString(customer.getName());
jsonGenerator.writeString(customer.getAddress());
jsonGenerator.writeEndArray();
}
}

View File

@@ -0,0 +1,81 @@
package com.baeldung.jsonoptimization;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
public class CustomerSlimShortNames {
@JsonProperty("i")
private long id;
@JsonProperty("n")
private String name;
@JsonProperty("a")
private String address;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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;
}
@Override
public int hashCode() {
return Objects.hash(address, id, name);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof CustomerSlimShortNames)) {
return false;
}
CustomerSlimShortNames other = (CustomerSlimShortNames) obj;
return Objects.equals(address, other.address) && id == other.id && Objects.equals(name, other.name);
}
@Override
public String toString() {
return "CustomerSlim [id=" + id + ", name=" + name + ", address=" + address + "]";
}
public static CustomerSlimShortNames[] fromCustomers(Customer[] customers) {
CustomerSlimShortNames[] feedback = new CustomerSlimShortNames[customers.length];
for (int i = 0; i < customers.length; i++) {
Customer aCustomer = customers[i];
CustomerSlimShortNames newOne = new CustomerSlimShortNames();
newOne.setId(aCustomer.getId());
newOne.setName(aCustomer.getFirstName() + " " + aCustomer.getLastName());
newOne.setAddress(aCustomer.getStreet() + ", " + aCustomer.getCity() + " " + aCustomer.getState() + " " + aCustomer.getPostalCode());
feedback[i] = newOne;
}
return feedback;
}
}

View File

@@ -0,0 +1,56 @@
package com.baeldung.jsontojavaclass;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import org.jsonschema2pojo.DefaultGenerationConfig;
import org.jsonschema2pojo.GenerationConfig;
import org.jsonschema2pojo.Jackson2Annotator;
import org.jsonschema2pojo.SchemaGenerator;
import org.jsonschema2pojo.SchemaMapper;
import org.jsonschema2pojo.SchemaStore;
import org.jsonschema2pojo.SourceType;
import org.jsonschema2pojo.rules.RuleFactory;
import com.sun.codemodel.JCodeModel;
public class JsonToJavaClassConversion {
public static void main(String[] args) {
String packageName = "com.baeldung.jsontojavaclass.pojo";
String basePath = "src/main/resources";
File inputJson = new File(basePath + File.separator + "input.json");
File outputPojoDirectory = new File(basePath + File.separator + "convertedPojo");
outputPojoDirectory.mkdirs();
try {
new JsonToJavaClassConversion().convertJsonToJavaClass(inputJson.toURI().toURL(), outputPojoDirectory, packageName, inputJson.getName().replace(".json", ""));
} catch (IOException e) {
System.out.println("Encountered issue while converting to pojo: " + e.getMessage());
e.printStackTrace();
}
}
public void convertJsonToJavaClass(URL inputJsonUrl, File outputJavaClassDirectory, String packageName, String javaClassName) throws IOException {
JCodeModel jcodeModel = new JCodeModel();
GenerationConfig config = new DefaultGenerationConfig() {
@Override
public boolean isGenerateBuilders() {
return true;
}
@Override
public SourceType getSourceType() {
return SourceType.JSON;
}
};
SchemaMapper mapper = new SchemaMapper(new RuleFactory(config, new Jackson2Annotator(config), new SchemaStore()), new SchemaGenerator());
mapper.generate(jcodeModel, javaClassName, packageName, inputJsonUrl);
jcodeModel.build(outputJavaClassDirectory);
}
}

View File

@@ -0,0 +1,213 @@
package com.baeldung.jsontojavaclass.pojo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"name",
"area",
"author",
"id",
"salary",
"topics"
})
@Generated("jsonschema2pojo")
public class SamplePojo {
@JsonProperty("name")
private String name;
@JsonProperty("area")
private String area;
@JsonProperty("author")
private String author;
@JsonProperty("id")
private Integer id;
@JsonProperty("salary")
private Integer salary;
@JsonProperty("topics")
private List<String> topics = new ArrayList<String>();
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("name")
public String getName() {
return name;
}
@JsonProperty("name")
public void setName(String name) {
this.name = name;
}
public SamplePojo withName(String name) {
this.name = name;
return this;
}
@JsonProperty("area")
public String getArea() {
return area;
}
@JsonProperty("area")
public void setArea(String area) {
this.area = area;
}
public SamplePojo withArea(String area) {
this.area = area;
return this;
}
@JsonProperty("author")
public String getAuthor() {
return author;
}
@JsonProperty("author")
public void setAuthor(String author) {
this.author = author;
}
public SamplePojo withAuthor(String author) {
this.author = author;
return this;
}
@JsonProperty("id")
public Integer getId() {
return id;
}
@JsonProperty("id")
public void setId(Integer id) {
this.id = id;
}
public SamplePojo withId(Integer id) {
this.id = id;
return this;
}
@JsonProperty("salary")
public Integer getSalary() {
return salary;
}
@JsonProperty("salary")
public void setSalary(Integer salary) {
this.salary = salary;
}
public SamplePojo withSalary(Integer salary) {
this.salary = salary;
return this;
}
@JsonProperty("topics")
public List<String> getTopics() {
return topics;
}
@JsonProperty("topics")
public void setTopics(List<String> topics) {
this.topics = topics;
}
public SamplePojo withTopics(List<String> topics) {
this.topics = topics;
return this;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
public SamplePojo withAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(SamplePojo.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("name");
sb.append('=');
sb.append(((this.name == null)?"<null>":this.name));
sb.append(',');
sb.append("area");
sb.append('=');
sb.append(((this.area == null)?"<null>":this.area));
sb.append(',');
sb.append("author");
sb.append('=');
sb.append(((this.author == null)?"<null>":this.author));
sb.append(',');
sb.append("id");
sb.append('=');
sb.append(((this.id == null)?"<null>":this.id));
sb.append(',');
sb.append("salary");
sb.append('=');
sb.append(((this.salary == null)?"<null>":this.salary));
sb.append(',');
sb.append("topics");
sb.append('=');
sb.append(((this.topics == null)?"<null>":this.topics));
sb.append(',');
sb.append("additionalProperties");
sb.append('=');
sb.append(((this.additionalProperties == null)?"<null>":this.additionalProperties));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
@Override
public int hashCode() {
int result = 1;
result = ((result* 31)+((this.area == null)? 0 :this.area.hashCode()));
result = ((result* 31)+((this.author == null)? 0 :this.author.hashCode()));
result = ((result* 31)+((this.topics == null)? 0 :this.topics.hashCode()));
result = ((result* 31)+((this.name == null)? 0 :this.name.hashCode()));
result = ((result* 31)+((this.id == null)? 0 :this.id.hashCode()));
result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode()));
result = ((result* 31)+((this.salary == null)? 0 :this.salary.hashCode()));
return result;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof SamplePojo) == false) {
return false;
}
SamplePojo rhs = ((SamplePojo) other);
return ((((((((this.area == rhs.area)||((this.area!= null)&&this.area.equals(rhs.area)))&&((this.author == rhs.author)||((this.author!= null)&&this.author.equals(rhs.author))))&&((this.topics == rhs.topics)||((this.topics!= null)&&this.topics.equals(rhs.topics))))&&((this.name == rhs.name)||((this.name!= null)&&this.name.equals(rhs.name))))&&((this.id == rhs.id)||((this.id!= null)&&this.id.equals(rhs.id))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.salary == rhs.salary)||((this.salary!= null)&&this.salary.equals(rhs.salary))));
}
}

View File

@@ -0,0 +1,32 @@
package com.baeldung.jsonvalidation;
import java.io.IOException;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
public class GsonValidator {
final TypeAdapter<JsonElement> strictAdapter = new Gson().getAdapter(JsonElement.class);
public boolean isValid(String json) {
try {
JsonParser.parseString(json);
} catch (JsonSyntaxException e) {
return false;
}
return true;
}
public boolean isValidStrict(String json) {
try {
strictAdapter.fromJson(json);
} catch (JsonSyntaxException | IOException e) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.jsonvalidation;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonValidator {
final ObjectMapper mapper = new ObjectMapper();
public boolean isValid(String json) {
try {
mapper.readTree(json);
} catch (JacksonException e) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,30 @@
package com.baeldung.jsonvalidation;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class JsonValidator {
public boolean isValidObject(String json) {
try {
new JSONObject(json);
} catch (JSONException e) {
return false;
}
return true;
}
public boolean isValidJson(String json) {
try {
new JSONObject(json);
} catch (JSONException e) {
try {
new JSONArray(json);
} catch (JSONException ne) {
return false;
}
}
return true;
}
}

View File

@@ -0,0 +1,119 @@
package com.baeldung.jsontojavaclass.pojo;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Generated;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"city",
"country"
})
@Generated("jsonschema2pojo")
public class Address {
@JsonProperty("city")
private String city;
@JsonProperty("country")
private String country;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("city")
public String getCity() {
return city;
}
@JsonProperty("city")
public void setCity(String city) {
this.city = city;
}
public Address withCity(String city) {
this.city = city;
return this;
}
@JsonProperty("country")
public String getCountry() {
return country;
}
@JsonProperty("country")
public void setCountry(String country) {
this.country = country;
}
public Address withCountry(String country) {
this.country = country;
return this;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
public Address withAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Address.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("city");
sb.append('=');
sb.append(((this.city == null)?"<null>":this.city));
sb.append(',');
sb.append("country");
sb.append('=');
sb.append(((this.country == null)?"<null>":this.country));
sb.append(',');
sb.append("additionalProperties");
sb.append('=');
sb.append(((this.additionalProperties == null)?"<null>":this.additionalProperties));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
@Override
public int hashCode() {
int result = 1;
result = ((result* 31)+((this.country == null)? 0 :this.country.hashCode()));
result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode()));
result = ((result* 31)+((this.city == null)? 0 :this.city.hashCode()));
return result;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Address) == false) {
return false;
}
Address rhs = ((Address) other);
return ((((this.country == rhs.country)||((this.country!= null)&&this.country.equals(rhs.country)))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))))&&((this.city == rhs.city)||((this.city!= null)&&this.city.equals(rhs.city))));
}
}

View File

@@ -0,0 +1,213 @@
package com.baeldung.jsontojavaclass.pojo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
"name",
"area",
"author",
"id",
"topics",
"address"
})
@Generated("jsonschema2pojo")
public class Input {
@JsonProperty("name")
private String name;
@JsonProperty("area")
private String area;
@JsonProperty("author")
private String author;
@JsonProperty("id")
private Integer id;
@JsonProperty("topics")
private List<String> topics = new ArrayList<String>();
@JsonProperty("address")
private Address address;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("name")
public String getName() {
return name;
}
@JsonProperty("name")
public void setName(String name) {
this.name = name;
}
public Input withName(String name) {
this.name = name;
return this;
}
@JsonProperty("area")
public String getArea() {
return area;
}
@JsonProperty("area")
public void setArea(String area) {
this.area = area;
}
public Input withArea(String area) {
this.area = area;
return this;
}
@JsonProperty("author")
public String getAuthor() {
return author;
}
@JsonProperty("author")
public void setAuthor(String author) {
this.author = author;
}
public Input withAuthor(String author) {
this.author = author;
return this;
}
@JsonProperty("id")
public Integer getId() {
return id;
}
@JsonProperty("id")
public void setId(Integer id) {
this.id = id;
}
public Input withId(Integer id) {
this.id = id;
return this;
}
@JsonProperty("topics")
public List<String> getTopics() {
return topics;
}
@JsonProperty("topics")
public void setTopics(List<String> topics) {
this.topics = topics;
}
public Input withTopics(List<String> topics) {
this.topics = topics;
return this;
}
@JsonProperty("address")
public Address getAddress() {
return address;
}
@JsonProperty("address")
public void setAddress(Address address) {
this.address = address;
}
public Input withAddress(Address address) {
this.address = address;
return this;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
public Input withAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(Input.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
sb.append("name");
sb.append('=');
sb.append(((this.name == null)?"<null>":this.name));
sb.append(',');
sb.append("area");
sb.append('=');
sb.append(((this.area == null)?"<null>":this.area));
sb.append(',');
sb.append("author");
sb.append('=');
sb.append(((this.author == null)?"<null>":this.author));
sb.append(',');
sb.append("id");
sb.append('=');
sb.append(((this.id == null)?"<null>":this.id));
sb.append(',');
sb.append("topics");
sb.append('=');
sb.append(((this.topics == null)?"<null>":this.topics));
sb.append(',');
sb.append("address");
sb.append('=');
sb.append(((this.address == null)?"<null>":this.address));
sb.append(',');
sb.append("additionalProperties");
sb.append('=');
sb.append(((this.additionalProperties == null)?"<null>":this.additionalProperties));
sb.append(',');
if (sb.charAt((sb.length()- 1)) == ',') {
sb.setCharAt((sb.length()- 1), ']');
} else {
sb.append(']');
}
return sb.toString();
}
@Override
public int hashCode() {
int result = 1;
result = ((result* 31)+((this.area == null)? 0 :this.area.hashCode()));
result = ((result* 31)+((this.address == null)? 0 :this.address.hashCode()));
result = ((result* 31)+((this.author == null)? 0 :this.author.hashCode()));
result = ((result* 31)+((this.topics == null)? 0 :this.topics.hashCode()));
result = ((result* 31)+((this.name == null)? 0 :this.name.hashCode()));
result = ((result* 31)+((this.id == null)? 0 :this.id.hashCode()));
result = ((result* 31)+((this.additionalProperties == null)? 0 :this.additionalProperties.hashCode()));
return result;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if ((other instanceof Input) == false) {
return false;
}
Input rhs = ((Input) other);
return ((((((((this.area == rhs.area)||((this.area!= null)&&this.area.equals(rhs.area)))&&((this.address == rhs.address)||((this.address!= null)&&this.address.equals(rhs.address))))&&((this.author == rhs.author)||((this.author!= null)&&this.author.equals(rhs.author))))&&((this.topics == rhs.topics)||((this.topics!= null)&&this.topics.equals(rhs.topics))))&&((this.name == rhs.name)||((this.name!= null)&&this.name.equals(rhs.name))))&&((this.id == rhs.id)||((this.id!= null)&&this.id.equals(rhs.id))))&&((this.additionalProperties == rhs.additionalProperties)||((this.additionalProperties!= null)&&this.additionalProperties.equals(rhs.additionalProperties))));
}
}

View File

@@ -0,0 +1,16 @@
{
"name": "Baeldung",
"area": "tech blogs",
"author": "Eugen",
"id": 32134,
"topics": [
"java",
"kotlin",
"cs",
"linux"
],
"address": {
"city": "Bucharest",
"country": "Romania"
}
}

View File

@@ -0,0 +1,95 @@
package com.baeldung.fastjson;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.BeanContext;
import com.alibaba.fastjson.serializer.ContextValueFilter;
import com.alibaba.fastjson.serializer.NameFilter;
import com.alibaba.fastjson.serializer.SerializeConfig;
import org.junit.Before;
import org.junit.Test;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class FastJsonUnitTest {
private List<Person> listOfPersons;
@Before
public void setUp() {
listOfPersons = new ArrayList<Person>();
Calendar calendar = Calendar.getInstance();
calendar.set(2016, 6, 24);
listOfPersons.add(new Person(15, "John", "Doe", calendar.getTime()));
listOfPersons.add(new Person(20, "Janette", "Doe", calendar.getTime()));
}
@Test
public void whenJavaList_thanConvertToJsonCorrect() {
String personJsonFormat = JSON.toJSONString(listOfPersons);
assertEquals(personJsonFormat, "[{\"FIRST NAME\":\"Doe\",\"LAST NAME\":\"John\",\"DATE OF BIRTH\":" + "\"24/07/2016\"},{\"FIRST NAME\":\"Doe\",\"LAST NAME\":\"Janette\",\"DATE OF BIRTH\":" + "\"24/07/2016\"}]");
}
@Test
public void whenJson_thanConvertToObjectCorrect() {
String personJsonFormat = JSON.toJSONString(listOfPersons.get(0));
Person newPerson = JSON.parseObject(personJsonFormat, Person.class);
assertEquals(newPerson.getAge(), 0); // serialize is set to false for age attribute
assertEquals(newPerson.getFirstName(), listOfPersons.get(0)
.getFirstName());
assertEquals(newPerson.getLastName(), listOfPersons.get(0)
.getLastName());
}
@Test
public void whenGenerateJson_thanGenerationCorrect() throws ParseException {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < 2; i++) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("FIRST NAME", "John" + i);
jsonObject.put("LAST NAME", "Doe" + i);
jsonObject.put("DATE OF BIRTH", "2016/12/12 12:12:12");
jsonArray.add(jsonObject);
}
assertEquals(jsonArray.toString(), "[{\"LAST NAME\":\"Doe0\",\"DATE OF BIRTH\":" + "\"2016/12/12 12:12:12\",\"FIRST NAME\":\"John0\"},{\"LAST NAME\":\"Doe1\"," + "\"DATE OF BIRTH\":\"2016/12/12 12:12:12\",\"FIRST NAME\":\"John1\"}]");
}
@Test
public void givenContextFilter_whenJavaObject_thanJsonCorrect() {
ContextValueFilter valueFilter = new ContextValueFilter() {
public Object process(BeanContext context, Object object, String name, Object value) {
if (name.equals("DATE OF BIRTH")) {
return "NOT TO DISCLOSE";
}
if (value.equals("John") || value.equals("Doe")) {
return ((String) value).toUpperCase();
} else {
return null;
}
}
};
JSON.toJSONString(listOfPersons, valueFilter);
}
@Test
public void givenSerializeConfig_whenJavaObject_thanJsonCorrect() {
NameFilter formatName = new NameFilter() {
public String process(Object object, String name, Object value) {
return name.toLowerCase()
.replace(" ", "_");
}
};
SerializeConfig.getGlobalInstance()
.addFilter(Person.class, formatName);
String jsonOutput = JSON.toJSONStringWithDateFormat(listOfPersons, "yyyy-MM-dd");
assertEquals(jsonOutput, "[{\"first_name\":\"Doe\",\"last_name\":\"John\"," + "\"date_of_birth\":\"2016-07-24\"},{\"first_name\":\"Doe\",\"last_name\":" + "\"Janette\",\"date_of_birth\":\"2016-07-24\"}]");
// resetting custom serializer
SerializeConfig.getGlobalInstance()
.put(Person.class, null);
}
}

View File

@@ -0,0 +1,69 @@
package com.baeldung.fastjson;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date;
public class Person {
@JSONField(name = "AGE", serialize = false, deserialize = false)
private int age;
@JSONField(name = "LAST NAME", ordinal = 2)
private String lastName;
@JSONField(name = "FIRST NAME", ordinal = 1)
private String firstName;
@JSONField(name = "DATE OF BIRTH", format = "dd/MM/yyyy", ordinal = 3)
private Date dateOfBirth;
public Person() {
}
public Person(int age, String lastName, String firstName, Date dateOfBirth) {
super();
this.age = age;
this.lastName = lastName;
this.firstName = firstName;
this.dateOfBirth = dateOfBirth;
}
@Override
public String toString() {
return "Person [age=" + age + ", lastName=" + lastName + ", firstName=" + firstName + ", dateOfBirth=" + dateOfBirth + "]";
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
}

View File

@@ -0,0 +1,85 @@
package com.baeldung.jsoniter;
import com.baeldung.jsoniter.model.Name;
import com.baeldung.jsoniter.model.Student;
import com.jsoniter.JsonIterator;
import com.jsoniter.ValueType;
import com.jsoniter.any.Any;
import org.junit.Test;
import static com.jsoniter.ValueType.STRING;
import static org.assertj.core.api.Assertions.assertThat;
public class JsoniterIntroUnitTest {
@Test
public void whenParsedUsingBindAPI_thenConvertedToJavaObjectCorrectly() {
String input = "{\"id\":1,\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Student student = JsonIterator.deserialize(input, Student.class);
assertThat(student.getId()).isEqualTo(1);
assertThat(student.getName().getFirstName()).isEqualTo("Joe");
assertThat(student.getName().getSurname()).isEqualTo("Blogg");
}
@Test
public void givenTypeInJsonFuzzy_whenFieldIsMaybeDecoded_thenFieldParsedCorrectly() {
String input = "{\"id\":\"1\",\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Student student = JsonIterator.deserialize(input, Student.class);
assertThat(student.getId()).isEqualTo(1);
}
@Test
public void whenParsedUsingAnyAPI_thenFieldValueCanBeExtractedUsingTheFieldName() {
String input = "{\"id\":1,\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Any any = JsonIterator.deserialize(input);
assertThat(any.toInt("id")).isEqualTo(1);
assertThat(any.toString("name", "firstName")).isEqualTo("Joe");
assertThat(any.toString("name", "surname")).isEqualTo("Blogg");
}
@Test
public void whenParsedUsingAnyAPI_thenFieldValueTypeIsCorrect() {
String input = "{\"id\":1,\"name\":{\"firstName\":\"Joe\",\"surname\":\"Blogg\"}}";
Any any = JsonIterator.deserialize(input);
assertThat(any.get("id").valueType()).isEqualTo(ValueType.NUMBER);
assertThat(any.get("name").valueType()).isEqualTo(ValueType.OBJECT);
assertThat(any.get("error").valueType()).isEqualTo(ValueType.INVALID);
}
@Test
public void whenParsedUsingIteratorAPI_thenFieldValuesExtractedCorrectly() throws Exception {
Name name = new Name();
String input = "{ \"firstName\" : \"Joe\", \"surname\" : \"Blogg\" }";
JsonIterator iterator = JsonIterator.parse(input);
for (String field = iterator.readObject(); field != null; field = iterator.readObject()) {
switch (field) {
case "firstName":
if (iterator.whatIsNext() == ValueType.STRING) {
name.setFirstName(iterator.readString());
}
continue;
case "surname":
if (iterator.whatIsNext() == ValueType.STRING) {
name.setSurname(iterator.readString());
}
continue;
default:
iterator.skip();
}
}
assertThat(name.getFirstName()).isEqualTo("Joe");
assertThat(name.getSurname()).isEqualTo("Blogg");
}
}

View File

@@ -0,0 +1,51 @@
package com.baeldung.jsonld.deserialization.jsonldjava.jackson;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.util.HashMap;
import org.junit.jupiter.api.Test;
import com.baeldung.jsonld.deserialization.jsonldjava.jackson.Person.Link;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.jsonldjava.core.JsonLdOptions;
import com.github.jsonldjava.core.JsonLdProcessor;
import com.github.jsonldjava.utils.JsonUtils;
public class JacksonDeserializationUnitTest {
@Test
void givenAJsonLdObject_whenCompactIsUsedWithEmptyContext_thenItCanBeDeserializedWithJackson() throws IOException {
String inputJsonLd = "{"
+ "\"@context\":{"
+ "\"@vocab\":\"http://schema.org/\","
+ "\"knows\":{\"@type\":\"@id\"}"
+ "},"
+ "\"@type\":\"Person\","
+ "\"@id\":\"http://example.com/person/1234\","
+ "\"name\":\"Example Name\","
+ "\"knows\":\"http://example.com/person/2345\""
+ "}";
Object jsonObject = JsonUtils.fromString(inputJsonLd);
Object compact = JsonLdProcessor.compact(jsonObject, new HashMap<>(), new JsonLdOptions());
String compactContent = JsonUtils.toString(compact);
assertEquals("{"
+ "\"@id\":\"http://example.com/person/1234\","
+ "\"@type\":\"http://schema.org/Person\","
+ "\"http://schema.org/knows\":{\"@id\":\"http://example.com/person/2345\"},"
+ "\"http://schema.org/name\":\"Example Name\""
+ "}", compactContent);
ObjectMapper objectMapper = new ObjectMapper();
Person person = objectMapper.readValue(compactContent, Person.class);
Person expectedPerson = new Person("http://example.com/person/1234", "Example Name", new Link("http://example.com/person/2345"));
assertEquals(expectedPerson.getId(), person.getId());
assertEquals(expectedPerson.getName(), person.getName());
assertEquals(expectedPerson.getKnows().getId(), person.getKnows().getId());
}
}

View File

@@ -0,0 +1,67 @@
package com.baeldung.jsonld.deserialization.jsonldjava.jackson;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Person {
@JsonProperty("@id")
private String id;
@JsonProperty("http://schema.org/name")
private String name;
@JsonProperty("http://schema.org/knows")
private Link knows;
public Person() {
}
public Person(String id, String name, Link knows) {
this.id = id;
this.name = name;
this.knows = knows;
}
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 Link getKnows() {
return knows;
}
public void setKnows(Link knows) {
this.knows = knows;
}
public static class Link {
@JsonProperty("@id")
private String id;
public Link() {
}
public Link(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
}

View File

@@ -0,0 +1,63 @@
package com.baeldung.jsonld.serialization.hydrajsonld;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
import de.escalon.hypermedia.hydra.serialize.JacksonHydraSerializer;
public class HydraJsonldSerializationUnitTest {
@Test
void givenAHydraJsonldAnnotatedObject_whenJacksonHydraSerializerIsUsed_thenAJsonLdDocumentIsGenerated() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(getJacksonHydraSerializerModule());
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Person person = new Person("http://example.com/person/1234", "Example Name");
String personJsonLd = objectMapper.writeValueAsString(person);
assertEquals("{"
+ "\"@context\":{"
+ "\"@vocab\":\"http://example.com/vocab/\","
+ "\"name\":\"fullName\""
+ "},"
+ "\"@type\":\"person\","
+ "\"name\":\"Example Name\","
+ "\"@id\":\"http://example.com/person/1234\""
+ "}", personJsonLd);
}
static SimpleModule getJacksonHydraSerializerModule() {
return new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
if (serializer instanceof BeanSerializerBase) {
return new JacksonHydraSerializer((BeanSerializerBase) serializer);
} else {
return serializer;
}
}
});
}
};
}
}

View File

@@ -0,0 +1,28 @@
package com.baeldung.jsonld.serialization.hydrajsonld;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.escalon.hypermedia.hydra.mapping.Expose;
import de.escalon.hypermedia.hydra.mapping.Vocab;
@Vocab("http://example.com/vocab/")
@Expose("person")
public class Person {
private String id;
private String name;
public Person(String id, String name) {
this.id = id;
this.name = name;
}
@JsonProperty("@id")
public String getId() {
return id;
}
@Expose("fullName")
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,33 @@
package com.baeldung.jsonld.serialization.jacksonjsonld;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import ioinformarics.oss.jackson.module.jsonld.JsonldModule;
public class JacksonJsonLdSerializationUnitTest {
@Test
void givenAJacksonJsonldAnnotatedObject_whenJsonldModuleIsUsed_thenAJsonLdDocumentIsGenerated() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JsonldModule());
Person person = new Person("http://example.com/person/1234", "Example Name");
String personJsonLd = objectMapper.writeValueAsString(person);
assertEquals("{"
+ "\"@type\":\"s:Person\","
+ "\"@context\":{"
+ "\"s\":\"http://schema.org/\","
+ "\"name\":\"s:name\","
+ "\"knows\":{\"@id\":\"s:knows\",\"@type\":\"@id\"}"
+ "},"
+ "\"name\":\"Example Name\","
+ "\"@id\":\"http://example.com/person/1234\","
+ "\"knows\":\"http://example.com/person/2345\""
+ "}", personJsonLd);
}
}

View File

@@ -0,0 +1,32 @@
package com.baeldung.jsonld.serialization.jacksonjsonld;
import ioinformarics.oss.jackson.module.jsonld.annotation.JsonldId;
import ioinformarics.oss.jackson.module.jsonld.annotation.JsonldLink;
import ioinformarics.oss.jackson.module.jsonld.annotation.JsonldNamespace;
import ioinformarics.oss.jackson.module.jsonld.annotation.JsonldProperty;
import ioinformarics.oss.jackson.module.jsonld.annotation.JsonldResource;
import ioinformarics.oss.jackson.module.jsonld.annotation.JsonldType;
@JsonldResource
@JsonldNamespace(name = "s", uri = "http://schema.org/")
@JsonldType("s:Person")
@JsonldLink(rel = "s:knows", name = "knows", href = "http://example.com/person/2345")
public class Person {
@JsonldId
private String id;
@JsonldProperty("s:name")
private String name;
public Person(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}

View File

@@ -0,0 +1,180 @@
package com.baeldung.jsonoptimization;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.zip.GZIPOutputStream;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.module.SimpleModule;
class JsonOptimizationUnitTest {
private static final String TEST_LABEL_JACKSON_DEFAULT_OPTIONS = "Default JSON";
private static final String TEST_LABEL_DEFAULT_JSON_NO_NULL = "Default JSON without null";
private static final String TEST_LABEL_SHORTER_FIELD_NAMES = "Shorter field names";
private static final String TEST_LABEL_SHORTER_FIELD_NAMES_AND_NO_NULL = "Shorter field names without null";
private static final String TEST_LABEL_SERIALIZING_TO_ARRAY = "Custom serializer";
private static final String TEST_LABEL_SLIM_CUSTOM_SERIALIZER = "Slim custom serializer";
private static final String TEST_LABEL_SLIM_CUSTOMER = "Slim customer";
private static final String TEST_LABEL_SLIM_CUSTOMER_SHORT_NAMES = "Slim customer with shorter field names";
private static DecimalFormat LENGTH_FORMATTER = new DecimalFormat("###,###.0");
private static DecimalFormat PERCENT_FORMATTER = new DecimalFormat("###.0");
private static Customer[] customers;
private ObjectMapper mapper;
private static int defaultJsonLength;
@BeforeAll
static void setUpOnce() throws Exception {
customers = Customer.fromMockFile();
ObjectMapper oneTimeMapper = new ObjectMapper();
byte[] feedback = oneTimeMapper.writeValueAsBytes(customers);
defaultJsonLength = feedback.length;
System.out.println();
System.out.println("Default JSON length: " + defaultJsonLength);
System.out.println();
}
@BeforeEach
void setUp() {
mapper = new ObjectMapper();
}
@Test
void whenSetUp_ThenOneThousandCustomers() {
assertEquals(1000, customers.length, "There should be a 1000 customers");
}
@Test
void whenJacksonDefaultOptions_thenValid() throws IOException {
printBanner(TEST_LABEL_JACKSON_DEFAULT_OPTIONS);
byte[] plainJson = createJsonAndVerify(TEST_LABEL_JACKSON_DEFAULT_OPTIONS, customers);
compressJson(TEST_LABEL_JACKSON_DEFAULT_OPTIONS, plainJson);
}
@Test
void whenExcludingNull_thenValid() throws IOException {
printBanner(TEST_LABEL_DEFAULT_JSON_NO_NULL);
mapper.setSerializationInclusion(Include.NON_NULL);
byte[] plainJson = createJsonAndVerify(TEST_LABEL_DEFAULT_JSON_NO_NULL, customers);
compressJson(TEST_LABEL_DEFAULT_JSON_NO_NULL, plainJson);
}
@Test
void whenShorterFieldNames_thenValid() throws IOException {
printBanner(TEST_LABEL_SHORTER_FIELD_NAMES);
CustomerShortNames[] shorterOnes = CustomerShortNames.fromCustomers(customers);
byte[] shorterJson = createJsonAndVerify(TEST_LABEL_SHORTER_FIELD_NAMES, shorterOnes);
compressJson(TEST_LABEL_SHORTER_FIELD_NAMES, shorterJson);
}
@Test
void whenShorterFieldNamesAndExcludingNull_thenValid() throws IOException {
printBanner(TEST_LABEL_SHORTER_FIELD_NAMES_AND_NO_NULL);
CustomerShortNames[] shorterOnes = CustomerShortNames.fromCustomers(customers);
mapper.setSerializationInclusion(Include.NON_NULL);
byte[] shorterJson = createJsonAndVerify(TEST_LABEL_SHORTER_FIELD_NAMES_AND_NO_NULL, shorterOnes);
compressJson(TEST_LABEL_SHORTER_FIELD_NAMES_AND_NO_NULL, shorterJson);
}
@Test
void whenSlimCustomer_thenValid() throws IOException {
printBanner(TEST_LABEL_SLIM_CUSTOMER);
CustomerSlim[] slimOnes = CustomerSlim.fromCustomers(customers);
byte[] slimJson = createJsonAndVerify(TEST_LABEL_SLIM_CUSTOMER, slimOnes);
compressJson(TEST_LABEL_SLIM_CUSTOMER, slimJson);
}
@Test
void whenSlimCustomerAndShorterFieldNames_thenValid() throws IOException {
printBanner(TEST_LABEL_SLIM_CUSTOMER_SHORT_NAMES);
CustomerSlimShortNames[] slimOnes = CustomerSlimShortNames.fromCustomers(customers);
byte[] slimJson = createJsonAndVerify(TEST_LABEL_SLIM_CUSTOMER_SHORT_NAMES, slimOnes);
compressJson(TEST_LABEL_SLIM_CUSTOMER_SHORT_NAMES, slimJson);
}
@Test
void whenSerializingToArray_thenValid() throws IOException {
printBanner(TEST_LABEL_SERIALIZING_TO_ARRAY);
SimpleModule serializer = new SimpleModule("CustomDeSerializer", new Version(1, 0, 0, null, null, null));
serializer.addSerializer(Customer.class, new CustomerSerializer());
serializer.addDeserializer(Customer.class, new CustomerDeserializer());
mapper.registerModule(serializer);
byte[] plainJson = createJsonAndVerify(TEST_LABEL_SERIALIZING_TO_ARRAY, customers);
compressJson(TEST_LABEL_SERIALIZING_TO_ARRAY, plainJson);
}
@Test
void whenSerializingToArrayAndSlimCustomer_thenValid() throws IOException {
printBanner(TEST_LABEL_SLIM_CUSTOM_SERIALIZER);
SimpleModule serializer = new SimpleModule("SlimCustomDeSerializer", new Version(1, 0, 0, null, null, null));
serializer.addSerializer(CustomerSlim.class, new CustomerSlimSerializer());
serializer.addDeserializer(CustomerSlim.class, new CustomerSlimDeserializer());
mapper.registerModule(serializer);
CustomerSlim[] slimOnes = CustomerSlim.fromCustomers(customers);
byte[] plainJson = createJsonAndVerify(TEST_LABEL_SLIM_CUSTOM_SERIALIZER, slimOnes);
compressJson(TEST_LABEL_SLIM_CUSTOM_SERIALIZER, plainJson);
}
private void printBanner(String name) {
System.out.println();
System.out.println("************************************************");
System.out.println("Testing " + name);
System.out.println();
}
void compressJson(String label, byte[] plainJson) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipStream = new GZIPOutputStream(outputStream);
gzipStream.write(plainJson);
gzipStream.close();
outputStream.close();
byte[] gzippedJson = outputStream.toByteArray();
double length = gzippedJson.length / 1024d;
double percent = gzippedJson.length * 100d / defaultJsonLength;
System.out.println(label + " GZIPped length: " + LENGTH_FORMATTER.format(length)
+ "kB (" + PERCENT_FORMATTER.format(percent) + "%)");
assertTrue(plainJson.length > gzippedJson.length, label + " should be longer than GZIPped data");
}
private byte[] createJsonAndVerify(String label, Object[] customers) throws IOException {
System.out.println(label + " sample: ");
ObjectWriter prettyWritter = mapper.writerWithDefaultPrettyPrinter();
System.out.println(prettyWritter.writeValueAsString(customers[0]));
byte[] feedback = mapper.writeValueAsBytes(customers);
double length = feedback.length / 1024d;
double percent = feedback.length * 100d / defaultJsonLength;
System.out.println(label + " length: " + LENGTH_FORMATTER.format(length)
+ "kB (" + PERCENT_FORMATTER.format(percent) + "%)");
assertTrue(feedback.length > 1, label + " should be there");
String prefix = label.replaceAll(" ", "-")
.toLowerCase();
File tempFile = File.createTempFile("jon-optimization-" + prefix, ".json");
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(feedback);
fos.close();
System.out.println(label + " file: " + tempFile.toString());
Object[] restoredOnes = mapper.readValue(feedback, customers.getClass());
assertArrayEquals(TEST_LABEL_JACKSON_DEFAULT_OPTIONS + ": restoring from JSON should work", customers, restoredOnes);
return feedback;
}
}

View File

@@ -0,0 +1,38 @@
package com.baeldung.jsontojavaclass;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Arrays;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class JsonToJavaClassConversionUnitTest {
private JsonToJavaClassConversion jsonToJavaConversion = new JsonToJavaClassConversion();
@Test
void whenProvideInputJSON_thenGenerateJavaClass() throws MalformedURLException, IOException {
String packageName = "com.baeldung.jsontojavaclass.pojo";
// load input JSON file
String jsonPath = "src/test/resources/";
File inputJson = new File(jsonPath + "sample_input.json");
// create the local directory for generating the Java Class file
String outputPath = "src/test/resources/";
File outputJavaClassDirectory = new File(outputPath);
String javaClassName = "SamplePojo";
jsonToJavaConversion.convertJsonToJavaClass(inputJson.toURI()
.toURL(), outputJavaClassDirectory, packageName, javaClassName);
File outputJavaClassPath = new File(outputPath + packageName.replace(".", "/"));
Assertions.assertTrue(Arrays.stream(outputJavaClassPath.listFiles()).peek(System.out::println).anyMatch(file -> (javaClassName+".java").equalsIgnoreCase(file.getName())));
}
}

View File

@@ -0,0 +1,35 @@
package com.baeldung.jsonvalidation;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class GsonValidatorUnitTest {
private final GsonValidator validator = new GsonValidator();
@Test
public void givenValidObjectJson_whenValidatingNonStrict_thenValid() {
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
}
@Test
public void givenValidArrayJson_whenValidatingNonStrict_thenValid() {
String json = "[{\"email\": \"example@com\", \"name\": \"John\"},{\"email\": \"example1@com\", \"name\": \"Bob\"}]";
assertTrue(validator.isValid(json));
}
@Test
public void givenInvalidJson_whenValidatingNonStrict_thenValid() {
String json = "Invalid_Json";
assertTrue(validator.isValid(json));
}
@Test
public void givenInvalidJson_whenValidatingStrict_thenInvalid() {
String json = "Invalid_Json";
assertFalse(validator.isValidStrict(json));
}
}

View File

@@ -0,0 +1,29 @@
package com.baeldung.jsonvalidation;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class JacksonValidatorUnitTest {
private final JacksonValidator validator = new JacksonValidator();
@Test
public void givenValidObjectJson_whenValidating_thenValid() {
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValid(json));
}
@Test
public void givenValidArrayJson_whenValidating_thenValid() {
String json = "[{\"email\": \"example@com\", \"name\": \"John\"},{\"email\": \"example1@com\", \"name\": \"Bob\"}]";
assertTrue(validator.isValid(json));
}
@Test
public void givenInvalidJson_whenValidating_thenInvalid() {
String json = "Invalid_Json";
assertFalse(validator.isValid(json));
}
}

View File

@@ -0,0 +1,35 @@
package com.baeldung.jsonvalidation;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class JsonValidatorUnitTest {
private final JsonValidator validator = new JsonValidator();
@Test
public void givenValidObjectJson_whenValidatingObject_thenValid() {
String json = "{\"email\": \"example@com\", \"name\": \"John\"}";
assertTrue(validator.isValidObject(json));
}
@Test
public void givenInvalidJson_whenValidating_thenInvalid() {
String json = "Invalid_Json";
assertFalse(validator.isValidObject(json));
}
@Test
public void givenValidArrayJson_whenValidatingObject_thenInvalid() {
String json = "[{\"email\": \"example@com\", \"name\": \"John\"},{\"email\": \"example1@com\", \"name\": \"Bob\"}]";
assertFalse(validator.isValidObject(json));
}
@Test
public void givenValidJson_whenValidatingJson_thenValid() {
String json = "[{\"email\": \"example@com\", \"name\": \"John\"},{\"email\": \"example1@com\", \"name\": \"Bob\"}]";
assertTrue(validator.isValidJson(json));
}
}

View File

@@ -0,0 +1,105 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.time.Instant;
import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.Test;
public class AlternativeAdapterUnitTest {
@Test
public void whenSerializing_thenAlternativeAdapterUsed() {
Moshi moshi = new Moshi.Builder()
.add(new EpochMillisAdapter())
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = jsonAdapter.toJson(new Post("Introduction to Moshi Json", "Baeldung", Instant.now()));
System.out.println(json);
}
@Test
public void whenDeserializing_thenAlternativeAdapterUsed() throws IOException {
Moshi moshi = new Moshi.Builder()
.add(new EpochMillisAdapter())
.build();
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
String json = "{\"author\":\"Baeldung\",\"posted\":1582095269204,\"title\":\"Introduction to Moshi Json\"}";
Post post = jsonAdapter.fromJson(json);
System.out.println(post);
}
public static class Post {
String title;
String author;
@EpochMillis Instant posted;
public Post() {
}
public Post(String title, String author, Instant posted) {
this.title = title;
this.author = author;
this.posted = posted;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Instant getPosted() {
return posted;
}
public void setPosted(Instant posted) {
this.posted = posted;
}
@Override
public String toString() {
return new ToStringBuilder(this).append("title", title).append("author", author).append("posted", posted)
.toString();
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@JsonQualifier
public @interface EpochMillis {
}
public static class EpochMillisAdapter {
@ToJson
public Long toJson(@EpochMillis Instant input) {
return input.toEpochMilli();
}
@FromJson
@EpochMillis
public Instant fromJson(Long input) {
return Instant.ofEpochMilli(input);
}
}
}

View File

@@ -0,0 +1,36 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import org.junit.Test;
public class ArrayUnitTest {
@Test
public void whenSerializingList_thenJsonArrayProduced() {
Moshi moshi = new Moshi.Builder()
.build();
Type type = Types.newParameterizedType(List.class, String.class);
JsonAdapter<List<String>> jsonAdapter = moshi.adapter(type);
String json = jsonAdapter.toJson(Arrays.asList("One", "Two", "Three"));
System.out.println(json);
}
@Test
public void whenDeserializingJsonArray_thenListProduced() throws IOException {
Moshi moshi = new Moshi.Builder()
.build();
Type type = Types.newParameterizedType(List.class, String.class);
JsonAdapter<List<String>> jsonAdapter = moshi.adapter(type);
String json = "[\"One\",\"Two\",\"Three\"]";
List<String> result = jsonAdapter.fromJson(json);
System.out.println(result);
}
}

View File

@@ -0,0 +1,94 @@
package com.baeldung.moshi;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import com.squareup.moshi.FromJson;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.ToJson;
import org.junit.Test;
public class ComplexAdapterUnitTest {
@Test
public void whenSerializing_thenCorrectJsonProduced() {
Moshi moshi = new Moshi.Builder()
.add(new JsonDateTimeAdapter())
.build();
JsonAdapter<ZonedDateTime> jsonAdapter = moshi.adapter(ZonedDateTime.class);
String json = jsonAdapter.toJson(ZonedDateTime.now());
System.out.println(json);
}
@Test
public void whenDeserializing_thenCorrectJsonConsumed() throws IOException {
Moshi moshi = new Moshi.Builder()
.add(new JsonDateTimeAdapter())
.build();
JsonAdapter<ZonedDateTime> jsonAdapter = moshi.adapter(ZonedDateTime.class);
String json = "{\"date\":\"2020-02-17\",\"time\":\"07:53:27.064\",\"timezone\":\"Europe/London\"}";
ZonedDateTime now = jsonAdapter.fromJson(json);
System.out.println(now);
}
public static class JsonDateTimeAdapter {
@ToJson
public JsonDateTime toJson(ZonedDateTime input) {
String date = input.toLocalDate().toString();
String time = input.toLocalTime().toString();
String timezone = input.getZone().toString();
return new JsonDateTime(date, time, timezone);
}
@FromJson
public ZonedDateTime fromJson(JsonDateTime input) {
LocalDate date = LocalDate.parse(input.getDate());
LocalTime time = LocalTime.parse(input.getTime());
ZoneId timezone = ZoneId.of(input.getTimezone());
return ZonedDateTime.of(date, time, timezone);
}
}
public static class JsonDateTime {
private String date;
private String time;
private String timezone;
public JsonDateTime() {
}
public JsonDateTime(String date, String time, String timezone) {
this.date = date;
this.time = time;
this.timezone = timezone;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
}
}

Some files were not shown because too many files have changed in this diff Show More