How can I import kotlin functions to java classes? - java

I am currently using KotlinModule class in my java file by importing import com.fasterxml.jackson.module.kotlin.KotlinModule;, but in recent jackson library upgrade (using 2.13) it is has been depricated. I was looking for the new convention, and came across this https://github.com/FasterXML/jackson-module-kotlin#usage
however I am not able to load the recommended functions in java file, i think that only works in Kotlin file. Is there an alternative?

This module uses Kotlin extension functions, they are all defined in an Extensions.kt file and as such are accessible by importing the ExtensionsKt class. For example :
import com.fasterxml.jackson.module.kotlin.ExtensionsKt;
import com.fasterxml.jackson.databind.ObjectMapper;
ObjectMapper mapper = ExtensionsKt.jacksonObjectMapper();
If the method extends a type, for example in Kotlin :
val mapper = ObjectMapper().registerKotlinModule()
The method is defined in kotlin as :
fun ObjectMapper.registerKotlinModule(): ObjectMapper
It will be converted in java to :
public static final ObjectMapper registerKotlinModule(#NotNull ObjectMapper $this$registerKotlinModule)
So to use it, you need to pass the extended type :
ObjectMapper mapper = ExtensionsKt.registerKotlinModule(new ObjectMapper());

Related

Jackson ObjectMappper Lowercase Strategy Not Working

I am writing a process that needs to pull JSON data from an API and provide it to another system that requires the field names to be completely lowercased. I have attempted to utilize the built in LowerCaseStrategy but this does not work. An example of what I have tried is:
package com.example
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
public class Example {
private static final ObjectMapper mapper = new ObjectMapper();
public Example(){
mapper.setPropertyNamingStrategy(new PropertyNamingStrategies.LowerCaseStrategy());
}
public JsonNode fetchData(String url) throws MalformedURLException, IOException{
JsonNode data = mapper.readTree(new URL(url));
return data;
}
}
A PropertyNamingStrategy affects how JSON property names are mapped from methods and fields in a Java class. This code doesn't do any mapping to Java objects, it only deserializes JSON into a JsonNode. In that case, PropertyNamingStrategy doesn't apply, and the names are retained from the original JSON source.
I was able to find the following gist which is working for me https://gist.github.com/stmcallister/92d0b4c2355a490ffed008cfbda69063
There's probably a better solution out there but this is perfect for my use case.

How can I find Annotated methods in Scala/Java on Runtime

I want to use Runtime Reflection with Scala annotations (could also be a Java annoations if necessary, but I would prefer to limit pure Java code)
I want to implement something like:
/**
print all methods that implement a specific annotation
*/
def getAllAnnotated(): Unit {...}
For example, if I have:
class Foo {
#printme
def foo(args: A): R
def oof(args: A): R
}
class Bar {
#printme
def bar(): Unit
}
The result of running getAllAnnotated() would be something like:
Foo.foo
Bar.bar
Note that I don't want to look in a specific class, but instead any available method
Try one of classpath scanners based on Java reflection (e.g. Reflections) + scala-reflect. Since we use Java reflection only to look for classes and scala-reflect to look for annotated methods, annotations can be written in Scala.
import org.reflections.Reflections
import org.reflections.scanners.SubTypesScanner
import org.reflections.util.{ClasspathHelper, ConfigurationBuilder}
import scala.annotation.StaticAnnotation
import scala.jdk.CollectionConverters._
import scala.reflect.runtime.currentMirror
import scala.reflect.runtime.universe._
class printme extends StaticAnnotation
val reflections = new Reflections(
(new ConfigurationBuilder)
.setUrls(ClasspathHelper.forPackage(""))
.setScanners(new SubTypesScanner(false))
)
def getAllAnnotated(): Unit =
reflections.getAllTypes.asScala
.flatMap(className =>
currentMirror.classSymbol(Class.forName(className))
.toType
.decls
.filter(symbol =>
symbol.isMethod && symbol.annotations.exists(_.tree.tpe =:= typeOf[printme])
)
.map(method => s"$className.${method.name}")
).foreach(println)
Alternatives to Reflections library are for example ClassGraph and Burningwave. If we replace scala-reflect with Java reflection then annotation will have to be written in Java because only annotations written in Java are visible at runtime with Java reflection.
In Java you can scan for the classes in the package using reflection Using Reflections to get all classes of the package and then recursively go inside all the classes to find the annotations.

scalaj-collections : Can I use this in Java?

I found scalaj-collections and it looks like it's the only library that will let me convert Java.util.List to scala.collection.Seq.
Can I use this library in my Java project? Or is exclusive to Scala. I've included its dependencies in my maven pom.xml and I can use the library in my code. But I don't see how to apply the .asScala method in a Java project
Thanks
You don't need thirdparty dependencies to convert between scala and java collections. Scala library has set of adapters named JavaConversions.
Just import scala.collection.JavaConversions._ and you'll get implicit conversions between scala and java collection interfaces, so you can pass them as the arguments to functions, call scala-specific methods on java collections (and vice versa) and so on.
import scala.collection.JavaConversions._
val sl = new scala.collection.mutable.ListBuffer[Int]
val jl : java.util.List[Int] = sl
jl.map(_ + 1)
val sl2 : scala.collection.mutable.Buffer[Int] = jl
Java.util.List to scala.collection.Seq
Scala has its own List (scala.collection.List). In addition, List has a function called toSeq(). I believe this is what you want.

FasterXML Jackson?

I'm switching to jackson json because it's apparently faster than minimal-json. I am however confused to how it works as the documentation is confusing.
Is it:
import com.fasterxml.jackson...
or:
import org.codehaus.jackson...
I have tried both, I have the file jackson-core-2.5.0.jar and the import com.fasterxml.jackson works, however I am not able to do the following:
ObjectMapper mapper = new ObjectMapper();
Jackson 1 was part of org.codehaus. Jackson 2 is now part of com.fasterxml and is in no way backwards compatible.
The ObjectMapper type is in the package com.fasterxml.jackson.databind.

How do i use Jackson Json parsing in a spring project without any annotations?

The Situation
I have an enum class called Errors and it is in a common project. The errors enum contains an int code and a String text. The Errors enum is used in two different projects. One project is a Spring based project and the other project is in a non-Spring J2EE application.
In the Spring based project, Jackson is the library used for converting the Errors enum to Json. So if there is a request we can return an Errors enum object and it will be automatically converted to the json representation, which is {code: int, text: error} The Errors enum has the annotation:
#JsonSerialize(using=ErrorsSerializer.class)
The ErrorsSerializer class is located in the Spring based application.
In the common project, where the Errors enum is located, Gson is the library used for converting objects to its Json representation and we want to remove any references to the Jackson library.
The problem
If i remove the annotation from the Errors enum the Spring project will not return the correct representation of the Errors enum, it will only return the constant variable in quotes.
The Question
How do i remove the annotation of the Errors enum (which will remove any Jackson dependencies in the common project) and yet still have the Spring project return the correct Json representation?
Best Option So Far
The best option i have come up with so far is to create an Errors container object in the Spring application that contains the Errors enum and also has the json serialize annotation.
Thanks!
You can also specify serializer in Spring based project using Module functionality. Module allow users to customize ObjectMapper object without annotations. See below example:
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class JacksonProgram {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addSerializer(Error.class, new ErrorJsonSerializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
System.out.println(mapper.writeValueAsString(Error.NOT_FOUND));
}
}
Above example prints:
{"code":1,"text":"Not found"}
See below links to find solution how to configure ObjectMapper in Spring app:
Register a custom Jackson ObjectMapper using Spring Javaconfig.
Configurating ObjectMapper in Spring.

Categories

Resources