Jackson's SORT_PROPERTIES_ALPHABETICALLY for Map - jackson

I use Jackson 2.5.0.
I would like to write a method which takes arbitrary JSON-string and sorts every property by key alphabetically with Jackson. Including nested ones.
I learned there is a SORT_PROPERTIES_ALPHABETICALLY feature of Jackson's ObjectMapper which I wanted to use in order to achieve my goal. So my initial code based on this idea is:
class FooBar {
String foo
String bar
}
def sortFields(String source) {
def om = new ObjectMapper().configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
def obj = om.readValue(source, Map.class)
return om.writeValueAsString(obj)
}
println sortFields('{"foo":"f","bar":"b"}')
Notice that I can't know ahead what structure input JSON has so Jackson unmarshalls it as a Map by default (LinkedHashMap to be more precise).
I expected it to output a string with keys sorted alphabetically:
{"bar":"b","foo":"f"}
Unfortunately with the snippet above SORT_PROPERTIES_ALPHABETICALLY does not work when object to serialize is a Map. If I replace Map.class with FooBar.class my JSON properties will be sorted as expected. But as I said, I can't know ahead a type of input JSON and have a class in my code for any type possible. What other options do I have with Jackson?

This works for the top level map:
objectMapper.configure(
SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true
);
Sadly it doesn't sort keys in any potential nested map you may have.

Related

Jooq: JsonConverter not converting jsonb into list of class when fetching data

This is a continuation of a first question I asked here: Jooq: How can I map a JSONB column to a Kotlin data class field?
Although I'm able to create new records just fine with the changes mentioned there, I'm not being able to fetch data like so:
fun findAllTrackedEvents(): List<TrackedEvent> {
return dslContext.select(*TRACKED_EVENT.fields())
.from(TRACKED_EVENT)
.fetchInto(TrackedEvent::class.java)
}
It seems that jackson is mapping the rows into LinkedHashMaps instead of mapping them into the fields of the Metadata data class. This is the error I'm getting:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON:
object is not an instance of declaring class; nested exception is com.fasterxml.jackson.databind.JsonMappingException:
object is not an instance of declaring class (through reference chain: java.util.ArrayList[0]->com.my.project.tracked_event.TrackedEvent["metadata"]->java.util.ArrayList[0]->java.util.LinkedHashMap["tableRef"])]
data class TrackedEvent(
val id: UUID,
// other fields
val metadata: List<Metadata> // this metadata field in the database is of type jsonb
)
data class Metadata(
val tableRef: String,
val value: UUID
)
So it can convert the field properly when inserting but not when fetching?
In my previous answer, I suggested you use arrays instead of lists. This had a reason. Consider this:
fun main() {
val a: Array<Int?> = arrayOf(1)
println(a::class.java)
val b: List<Int?> = listOf(1)
println(b::class.java)
}
It prints:
class [Ljava.lang.Integer;
class java.util.Collections$SingletonList
As you can see, while arrays are reified on the JVM, other generic types are not, and the T type variable of List<T> is erased. It is possible that Jackson cannot figure out the correct type to unmarshal at runtime using reflection, despite all the type information being available at compile time.
I would just use Array<Metadata> instead. Alternatively, of course, you can attach a custom converter to the column, instead of using the out of the box <jsonConverter>. That way, you're in full control of the mapping.

How to create JSON object strategy according to a schema with rust proptest?

I'd like to create a JSON strategy using rust proptest library. However, I do not want to create an arbitrary JSON. I'd like to create it according to a schema (more specifically, OpenAPI schema). This means that keys of the JSON are known and I do not want to create them using any strategy, but I'd like to create the values using the strategy (pretty-much recursively).
I already implemented the strategy for primitive types, but I do not how to create a JSON object strategy.
I would like the strategy to have the type BoxedStratedy<serde_json::Value> or be able to map the strategy to this type because the JSON objects can contain other objects, and thus I need to be able to compose the strategies.
I found a HashMapStrategy strategy, however, it can be only created by a hash_map function that takes two strategies - one for generating keys and one for values. I thought that I could use Just strategy for the keys, but it did not lead anywhere. Maybe prop_filter_map could be used.
Here is the code. There are tests too. One is passing because it tests only primitive type and the other is failing since I did not find a way to implement generate_json_object function.
I tried this but the types do not match. Instead of a strategy of map from string to JSON value, it is a strategy of a map from string to BoxedStrategy.
fn generate_json_object(object: &ObjectType) -> BoxedStrategy<serde_json::Value> {
let mut json_object = serde_json::Map::with_capacity(object.properties.len());
for (name, schema) in &object.properties {
let schema_kind = &schema.to_item_ref().schema_kind;
json_object.insert(name.clone(), schema_kind_to_json(schema_kind));
}
Just(serde_json::Value::Object(json_object)).boxed()
}
One can create a vector of strategies, which implements a Strategy trait and can be boxed. So to create a serde_json::Value::Object, we create a vector of tuples. The first element will be a Just of key and the second element will be a boxed strategy of value. The boxed strategy of value can be created by schema_kind_to_json function. After we have a vector of tuples which implement a Strategy, we can use .prop_map to transform it to a serde_json::Value::Object.
fn generate_json_object(object: &ObjectType) -> BoxedStrategy<serde_json::Value> {
let mut vec = Vec::with_capacity(object.properties.len());
for (name, schema) in &object.properties {
let schema_kind = &schema.to_item_ref().schema_kind;
vec.push((Just(name.clone()), schema_kind_to_json(schema_kind)));
}
vec.prop_map(|vec| serde_json::Value::Object(serde_json::Map::from_iter(vec)))
.boxed()
}

Kotlin: get members of a data class by reflection in the order they have been defined

Assume the following simple example data class:
data class SomeDataClass(
var id: String,
var name: String,
var deleted: String
)
With the following code it is possible to get the properties (and set or get their values):
import kotlin.reflect.full.memberProperties
val properties = SomeDataClass::class.memberProperties
print(properties.map { it.name }) // prints: [deleted, id, name]
The map within the print statement will return a List with the name of the properties in alphabetical order. I need the list in the order they have been defined in the source code, in this case: [id, name, deleted].
It doesn't seem achievable purely through reflection. The only solution I could come up with is to use a helper class defining the order:
val SomeDataClass_Order = listOf("id", "name", "deleted")
This wouldn't be a problem for one or two classes, but it is for hundreds of data classes with the largest one having up to almost one hundred properties.
Any idea would be welcome. I do not need detailed code, rather hints (like parsing the source code, annotations, etc).
If all the properties are declared in the primary constructor, you could "cheat":
val propertyNames = SomeDataClass::class.primaryConstructor!!.parameters.map { it.name }
If you want the KPropertys:
val properties = propertyNames.map { name ->
SomeDataClass::class.memberProperties.find { it.name == name }
}
This unfortunately doesn't find the properties that are declared in the class body.
I don't know about other platforms, but on Kotlin/JVM, the order in which the backing fields for the properties are generated in the class file is not specified, and a quick experiment finds that the order (at least for the version of kotlinc that I'm using right now), the order is the same as the declaration order. So in theory, you could read the class file of the data class, and find the fields. See this related answer for getting the methods in order. Alternatively, you can use Java reflection, which also doesn't guarantee any order to the returned fields, but "just so happens" to return them in declaration order:
// not guaranteed, might break in the future
val fields = SomeDataClass::class.java.declaredFields.toList()
If you do want to get the properties declared inside the class body in order too, I would suggest that you don't depend on the order at all.

Simple Jackson Array string addition

I am trying to convert GSON to jackson I have a method that returns a gson JsonObject. However it only creates a JsonArray, and returns that so I assume there is a simple casting there. So what would be the Jackson Equivalent? Now the method only adds one string at a time. So I need something like this:
JsonNode node = new JsonNode();
node.add("String 1");
node.add("String 2');
but would come out like this:
["String 1","String 2"]
I could create a List and map it from there, but I want to do this raw.
This seems too simple as google has given me many suggestions that are far beyond what this simple exercise requires.
And if anyone has a nice blog to tutorial on how to convert Gson to Jackson that would be great.
it is a bit tricky - you create an array node through JsonNode factory method:
ArrayNode arrNode = (ArrayNode)new JsonNode().withArray("my_array"); // arg is arrray propertry name
arrNode.add("String 1");
arrNode.add("String 2');
If you just want to create ArrayNode, ObjectMapper has method createArrayNode(), along with createObjectNode(). You can then add entries to it, as well as add node itself into other arrays, or as property in ObjectNode.
Actual construction of nodes by mapper is done using configurable JsonNodeFactory; default implementation of which simple constructs one of standard implementation types like ObjectNode and ArrayNode.

Transforming an object hierarchy using Jackson

I would like to leverage the Jackson infrastructure to transform an untyped Map/List structure into a POJO hierarchy.
What I need is pretty close to
jsonNode = objectMapper.valueToTree(MapHierarchy) followed by
pojoTree = objectMapper.treeToValue(jsonNode)
...except that I need to modify the field names on the fly: the names found in the source Map/List hierarchy are declared as custom annotations on the POJO class.
Here is a complete example:
public class Cat
{
#MapField("attr:col")
#JsonProperty("color")
private String _color;
}
... and the source Map:
{
"attr:col" -> "black"
}
... from which I would like to obtain a Cat instance.
I am sure there has got to be an elegant way to achieve this with the Jackson APIs, but I can't quite figure out how... any suggestions? Obviously I don't want to create a second parallel class hierarchy just to describe the deserialization of the Map through annotations.
An extra bonus would be to be able to transform the Map without going through stringified JSon which I believe is how valueToTree works.