Create POJO Class for Kotlin - java

I want to create POJO class for Kotlin, as we know that www.jsonschema2pojo.org converts JSON to POJO so we can use it with gson.
Anyone know how to create Gson POJO for Kotlin QUICKLY?
Edited:
I know its use Data classes, but is there any simplest way to create it?

I think this should be the Plugin what you want
https://github.com/wuseal/JsonToKotlinClass

Yes, I got solution
for Example:
{
"foo": "string",
"bar": "integer",
"baz": "boolean"
}
My POJO Class Created using http://www.jsonschema2pojo.org/
Example.java
public class Example {
#SerializedName("foo")
#Expose
private String foo;
#SerializedName("bar")
#Expose
private String bar;
#SerializedName("baz")
#Expose
private String baz;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
public String getBaz() {
return baz;
}
public void setBaz(String baz) {
this.baz = baz;
}
}
Converted Kotlin Class using Code -> Convert Java File to Kotlin File or CTRL + ALT + SHIFT + K
Example.kt
class Example {
#SerializedName("foo")
#Expose
var foo: String? = null
#SerializedName("bar")
#Expose
var bar: String? = null
#SerializedName("baz")
#Expose
var baz: String? = null
}
Thank you all.

data class ModelUser(val imagePath: String,val userName: String)
Unbelievable Right! Its as simple as that. Just use data keyword before class to create Data class in Kotlin.
Data class provides you with everything, getters, setters, hashCode, toString and equals functions. So all you have to do is create an instance and start using the functions.

A feature request about Kotlin support to auto generate data classes have been filled here in jsonschema2pojo github repository.
Currently, there is no jsonschema2kotlin web utility available.
If you don't have any problem installing a new plugin on Android Studio, follow the accepted answer, otherwise the best you can do is to use jsonschema2pojo to convert JSON to Java POJO and the use the Android Studio 3.0+ feature that converts a Java file to a Kotlin one.

In vs-code there is a plugin named Paste JSON as Code.
it supports many languages.
Paste Json as code

If I got your question, you might be searching some plugin for converting to POJO. So
RoboPOJOGenerator
may help you. You can use a plugin from File>Setting>Plugin>Browse Repositories and search for RoboPOJOGenerator.
To use this plugin you first need to create a separate package like "data", right-click the package and you will see Generate POJO from JSON. Also, you need to include gson library in gradle because this plugin will automatically generate annotation of gson like #SerializedName, etc.

Try this
This is the simple way
Right-click on the package name and select New->Kotlin File/Class
Name the name (in my case, I am naming this as Model, you can name it whatever you like) and click OK.
Paste this code, this is your POJO/Model class:
class Model {
var uid: String? = null
var name: String? = null
}
How to use this
val model = Model()
model.name = "Sunil"
Log.e("Model after", model.name)

Use the Android Studio or IntelliJ IDEA plugin:
JSON To Kotlin Class ​(JsonToKotlinClass)​

In my case Code -> Generate doesn't work, it is disabled (see screenshot)
You should install the plugin "JsonToKotlinClass"
Then right-click on the namespace and select
Paste your JSON here. That's all, profit.

data class VideoGame(val name: String, val publisher: String, var reviewScore: Int)
//Constructor
val game: VideoGame = VideoGame("Gears of War", "Epic Games", 8)
print(game.name) // "Gears of War"
print(game.publisher) // "Epic Games"
print(game.reviewScore) // 8
game.reviewScore = 7

Related

Mapping part of a JSON string to an abstract class using GSON

I have a json string that I would like to map to my java object. I am currently using gson to do so. The problem is however, I have setup part of my POJO to contain an abstract class. How can I map the json that corresponds to this abstract class correctly?
To clarify:
Here is an example of a json string I am currently receiving:
{
"Items" : [
{
"id" : "ID1",
"seller_id": 17,
"item_plan": {
"action" : "Sell"
}
},
{
"id" : "ID2",
"seller_id": 27,
"item_plan": {
"action": "Remove",
}
}
]
}
My request object is setup like so:
public class RequestObject {
#SerializedName("Items")
#Expose
private List<Item> items = null;
public class Item {
#SerializedName("id")
#Expose
private String id;
#SerializedName("seller_id")
#Expose
private Integer sellerID;
#SerializedName("item_Plan")
#Expose
private ItemPlan item_plan;
public abstract class ItemPlan {
#SerializedName("action")
#Expose
private String action;
public abstract void executePlan()
As you can see, my request object has an abstract class that represents item_plan. The idea here is that item_plan actions will have their own way of execution and therefore have a parent class called ItemPlan where each child class would represent the possible action plans and their own executionPlan ie. (SellPlan is a child class of ItemPlan, where SellPlan has its own implementation of the function executionPlan()).
How can I map my example json string to the following Java classes?
I have tried the following:
RuntimeTypeAdapterFactory<ItemPlan> itemPlanRuntimeTypeAdapterFactory =
RuntimeTypeAdapterFactory
.of(ItemPlan.class, "action")
.registerSubtype(SellPlan.class, "Sell")
.registerSubtype(RemovePlan.class, "Remove");
Gson gson = new
GsonBuilder().registerTypeAdapterFactory(itemPlanRuntimeTypeAdapterFactory).create();
RequestObject request = gson.fromJson(jsonString, RequestObject.class);
This, however, does not work. It is able to map everything I need but it fails to create the correctly create the abstracted class objects ie. while it will create the corresponding child objects (SellPlan for Sell and RemovePlan for Remove), it will make the action string of those classes null. There is a workaround where I can simply set the action string manually in the constructor of these classes but I would rather not. Is there a way to fix this?
Thank you.
You probably have to use the RuntimeTypeAdapterFactory.of overload with the additional maintainType parameter for which you then pass true as value. Otherwise, as you have noticed, Gson removes the type field value during serialization, and therefore the field keeps its default value null.

Handle Json non existent keys spring boot

I am creating a requestModel and let say a person doesn't send me some keys.
If that key is not present I want to put null if i get the value of the key.
I don't want to investigate if a key is present or not .
public class CustomerModel {
private Optional<String> s3Bucket;
private Optional<String> docType;
public String getS3Bucket() {
if(s3Bucket.isPresent()) {
return s3Bucket.get();
} else {
return null;
}
}
public void setS3Bucket(Optional<String> s3Bucket) {
this.s3Bucket = s3Bucket;
}
public Optional<String> getDocType() {
return docType;
}
public void setDocType(Optional<String> docType) {
this.docType = docType;
}
}
Do we have any library or something where.
1. If i get the key and it is not present in the coming request json, i will get the null out of it and if the key is present and has value . It will be stored as value.
2. When writing the getter for s3bucket (getS3Bucket), i dont want to write it for everykey value. Is there a automatic way to do this.
I looked at lot of posts but the scenario is not there.
P.S - I am new to java
I believe Jackson is exactly what you need. And if you are using Spring - it already uses Jackson under the hood I guess.
Here you can find some examples and documentation of how JSON mapping on to model class is done.
If you need to customize some behavior, you can use annotations like #JsonProperty (there are many).
If properties in your model class have the same names as properties in JSON, most probably you won't need to provide any further configs.
Here is a simple example:
public class User {
#JsonProperty("userName")
private String name;
private int age;
// getters and setters
}
And if you have JSON like this:
{
"userName" : "Foo Bar",
"age" : 18
}
Jackson will do all the magic for you unless you need something very specific.
If something is not in JSON you get (let's say you received JSON without age) - corresponding property in model class will be null if it is object type and default value (0, false, etc.) for primitives (in our case age would be 0).

Kotlin: Change the json property name depending on the #JsonView

I am trying to use Jackson to serialize the same DTO object in 2 different ways, depending on the #JsonView.
I want to use 2 different names for the same field. In one case I want to name the json property myField (just like the class field name), in the other I want it to be named myInternalApiField.
As a result I would like to see outcomes similar to the presented below:
Usage 1 (External API View):
{
"myField": "value1",
"myOtherField": "otherValue"
}
Usage 2 (Internal API View):
{
"myInternalApiField": "value1",
"myOtherField": "otherValue"
}
In my implementation in Java to achieve that I used the combination of custom getters, setters and #JsonView annotation as below:
public class CustomDTO {
#JsonView(Views.ExternalApiView)
private String myField;
// Other fields here
#JsonView(Views.InternalApiView)
public String getMyInternalApiField() { return myField; }
#JsonView(Views.InternalApiView)
public void setMyInternalApiField(String value) { this.myField = value; }
#JsonView(Views.ExternalApiView)
public String getMyField() { return myField; }
#JsonView(Views.ExternalApiView)
public void setMyField(String value) { this.myField = value }
}
However I don't know how to properly achieve the same result in Kotlin.
I was thinking about using something like:
data class CustomDTO(
#get:[JsonView(Views.ExternalApiView) JsonProperty("myField")]
#get:[JsonView(Views.InternalApiView) JsonProperty("myInternalApiField")]
#set:[JsonView(Views.InternalApiView) JsonProperty("myField")]
#set:[JsonView(Views.InternalApiView) JsonProperty("myInternalApiField")]
var myField: String,
val myOtherField: String,
val myDifferentField: String
)
But this is not allowed in Kotlin.
Do you have any suggestions how to utilize the #JsonView in Kotlin in the similar way as I did it in Java?
How about something like:
data class CustomDTO(
#JsonView(ExternalApiView::class)
var myField: String,
val myOtherField: String,
val myDifferentField: String
) {
val myExternalField: String
#JsonView(InternalApiView::class)
get() {
return myField
}
}
It looks like there are ways that don't require creating computed properties in the DTO, like:
Using Jackson Mixins
Creating a custom serializer for a particular invocation
Combining a custom serializer with custom annotations
But these have their own complexity, even if that complexity isn't in the DTO class. I'm not sure these are much more appealing to me but you could see if they appeal to you.

Issue with replacing Java DTO classes with Kotlin Data classes

I read about Kotlin data classes and thought that they could be pretty useful in cases with describing data transfer objects (DTOs). In my Java project I already has DTO classes written on Java, something like:
public class Tweet {
private String id;
private String profileId;
private String message;
public Tweet() {}
public String getId() {
return id;
}
public String getProfileId() {
return profileId;
}
public String getMessage() {
return message;
}
public void setId(String id) {
this.id = id;
}
public void setProfileId(String profileId) {
this.profileId = profileId;
}
public Tweet setMessage(String message) {
this.message = message;
return this;
}
}
These DTO classes are stored in separate artifact which I add as a dependency to other artifacts. So, I decided to replace it with Kotlin classes and rewrote mentioned Tweet class on Kotlin, so it started to looks like:
data class Tweet(var id: String? = null,
var profileId: String? = null,
var message: String? = null)
It's my first experience with Kotlin, so possibly there are something that can looks ugly, but my main issue is - when I try to rebuild artifacts which use my DTOs as dependencies, I get such exception:
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
at io.vertx.core.json.Json.decodeValue(Json.java:117)
at gk.tweetsched.api.repository.TweetRepository.get(TweetRepository.java:51)
at gk.tweetsched.api.repository.TweetRepositoryTest.testGet(TweetRepositoryTest.java:68)
Caused by: java.lang.ClassNotFoundException:
kotlin.jvm.internal.DefaultConstructorMarker
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 67 more
As I see according that stacktrace Jackson couldn't deserialize JSON to Tweet Kotlin class.
Here is my Java method where I get that exception:
public Tweet get(String id) {
try (Jedis jedis = pool.getResource()) {
return Json.decodeValue(jedis.hget(TWEETS_HASH, id), Tweet.class);
} catch (Exception e) {
LOGGER.error(e);
}
return null;
}
Where Json class is from 'io.vertx.core.json' package.
How can I fix that issue? Which additional configurations should I make in my Java projects to use Kotlin classes?
By default Jackson needs a parameterless constructor to deserialize JSON to a class - Kotlin data classes do not have one, so you need to add a Jackson module to handle this:
jackson-module-kotlin
Edit:
I've read the source for io.vertx.core.json.Json class and it seems that both object mappers used by the class are stored in public static fields.
So to register jackson-module-kotlin you need to include this snippet in your application initialization code (or anywhere else really as long as it is executed before you attempt to deserialize any Kotlin data classes):
Json.mapper.registerModule(new KotlinModule())
Json.prettyMapper.registerModule(new KotlinModule())
In my case, I create kotlin class DTO instance in java for consuming RESTful Api.
Now I have 2 solutions tested:
Use parameterless constructor in data class.
The reference kotlin says:
On the JVM, if all of the parameters of the primary constructor have
default values, the compiler will generate an additional parameterless
constructor which will use the default values. This makes it easier to
use Kotlin with libraries such as Jackson or JPA that create class
instances through parameterless constructors.
So I have a DTO in kotlin like this:
data class Dto (
var id: Int?=null,
var version: Int?=null,
var title: String?=null,
var firstname: String?=null,
var lastname: String?=null,
var birthdate: String?=null
)
Then, I create class instance DTO in java:
Dto dto = new Dto();
dto.setId(javadto.getId());
...
Use plugin jackson-module-kotlin
import com.fasterxml.jackson.annotation.JsonProperty
data class Dto (
#JsonProperty("id") var id: Int?,
#JsonProperty("version") var version: Int?,
#JsonProperty("title") var title: String?,
#JsonProperty("firstname") var firstname: String?,
#JsonProperty("lastname") var lastname: String?,
#JsonProperty("birthdate") var birthdate: String?,
)
Then, I create class instance DTO in java:
Dto dto = new Dto(null, null, null, null, null, null);
dto.setId(javadto.getId());
...

Dynamic JSON serialization based on the property value

I am implementing a REST server using Spring Boot, JAXB2 and Jackson. This server supports JSON and XML and it is based on official specifications.
I am currently having a serialization problem specific to the JSON format and I do not know how it can be solved?
The specification defines several primitive types as string, integer, etc. that can be extended and depending of this extension, the result of the serialization is not the same.
The Java classes
public class PrimitiveType {
#XmlAttribute
private String id
#XmlElement(name = "extension")
private List<Extension> extensions = new ArrayList<>();
// Getters and Setters
}
public class StringType extends PrimitiveType {
#XmlAttribute
private String value;
// Getter and Setter
}
JSON
// Without id and/or extension(s)
"code" : "abc"
// With id and/or extension(s)
"code ": "abc",
"_code": {
"id": "1",
"extension" : [ {
"url" : "http://mydomain/ext/1",
"valueString" : "abc-1"
}]
}
I do not have any problem with the XML but it is not the same for the JSON. I do not know how I can add a property dynamically on the same level. I had a look on the JsonSerializer but it seems that it allows to change the serialization on the object itself.
Does anyone had a chance to do this kind of things before?

Categories

Resources