Webclient serializing booleans with initial underscore - serialization

public MyClass {
private String field1;
private String field2;
private boolean field3;
public MyClass() {
this.field1 = "value1";
this.field2 = "value2";
this.field3 = false;
}
getters/setters...
}
When passing it to Webclient as the body of a post, the JSON that gets generated is:
{
"field1": "value1",
"field2": "value2",
"_field3": on
}
with field3's name changed and having a value that is always 'on'.
I haven't found a way to disable this: is it possible? Am I doing something wrong?
I tried adding #JsonProperty to the field and #JsonObject to the class but nothing changed. I'd expect the Json to be:
{
"field1": "value1",
"field2": "value2",
"field3": false
}
which is what the webservice is expecting.

Related

Spring Hateoas: EntityModel _links rendered before content

This is a weird problem to describe since it's no actually a problem in the technical sense but still makes me curious enough to ask about it:
I created a #RestController that returns ResponseEntity<EntityModel<?>>. I build the EntityModel and attach a self link built with linkTo and methodOn. Now for some reason, the output looks like this:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/points/knx/office_light"
}
},
"labels" : {
"name" : "Light",
"room" : "Office"
},
"access" : [ "READ", "WRITE" ],
"type" : "SwitchPoint",
"state" : "OFF"
}
Contrary to other rest services I have build, the "_link" gets rendered at the top not at the bottom. Any ideas why?
#GetMapping("{ext}/{id}")
public ResponseEntity<EntityModel<Map<String, Object>>> oneByExt(#PathVariable String ext,
#PathVariable String id) {
EntityModel<Map<String, Object>> point = client.getPoint(ext, id);
return new ResponseEntity<>(localToGlobal(ext, point), HttpStatus.OK);
}
private <T> EntityModel<T> localToGlobal(String ext, EntityModel<T> model) {
ComposedId id = ComposedId.fromEntityModel(ext, model);
Link newSelfLink = linkTo(methodOn(PointController.class).oneByExt(id.getExtension(), id.getIdentifier()))
.withSelfRel();
EntityModel<T> newModel = EntityModel.of(model.getContent());
newModel.add(newSelfLink);
return newModel;
}
It's probably due to the Map, I'm assuming you using something like HashMap which has no guarantee of iteration order. Try change it to a LinkedHashMap and see what happens (should print the values in the order they were added to the map)

Access build.gradle.kt values

The question was: how to access from your Kotlin code, a arbitrary value that exists in build.gradle.kt?
If you have the following entry in my build.gradle.kt file (trying to add a feature flag):
android {
...
buildTypes {
getByName("debug") {
buildConfigField("Boolean", "FOO", "true")
}
getByName("release") {
buildConfigField("Boolean", "FOO", "false")
}
}
...
}
A way to access the value of FOO within your Kotlin code is:
class FeatureFlag {
fun isFeatureEnabled(): Boolean = BuildConfig.FOO
}
Use buildConfigField instead of resValue. Same arguments. Then in Kotlin code:
class FeatureFlag {
fun isFeatureEnabled(): Boolean =
BuildConfig.FOO.toBoolean()
}
Although I'm not sure why you don't just use a "boolean" type to begin with instead of a String that you have to convert to Boolean at runtime.

Pick any element from JSON schema while streaming data to parse

I'm writing a de-serializer which reads a huge json file and puts records matching a filter (logic in my application) into database. The json file has a fixed schema as follows:
{
"cityDetails": {
"name": "String",
"pinCodes": "Array of integers ",
"people": [{
"name": "String",
"age": "Integer"
}]
}
}
I am only interested in streaming list of "people" from the file. I am aware that GSON/Jackson provide streaming APIs which I can use but I want to avoid looping through the tokens as I stream them and match their name to see if I am interested in them. I believe that there should be a solution which can do the streaming in background and point/seek the stream to the token I am interested in. I don't see any reason why this should not be possible if I provide my JSON schema. Is there are solution available for this?
Here's a sample instance of my JSON:
{
"cityDetails": {
"name": "mumbai",
"pinCodes": ["400001", "400002"],
"people": [{
"name": "Foo",
"age": 1
}, {
"name": "Bar",
"age": 2
}]
}
}
With GSON I would just create corresponding DTOs for the data to be parsed.
So you have some wrapper that is the root object:
#Getter
public class Wrapper {
private CityDetails cityDetails;
}
and city details:
#Getter
public class CityDetails {
private List<Person> people;
}
and possibly many Persons in the list people:
#Getter
#ToString
public class Person {
private String name;
private Integer age;
}
Then you can simply use for example Reader like below:
#Test
public void test() {
Gson gson = new Gson();
// assuming your json is named "test.json" in the same directory as test
Reader r = new InputStreamReader(getClass().getResourceAsStream("test.json"));
Wrapper wrapper = gson.fromJson(r, Wrapper.class);
wrapper.getCityDetails().getPeople().forEach(p -> log.info("{}", p.toString()));
}
Gson will search and instantiate only what is specified in DTO-classes the rest is ignored when parsing.
A nice way of doing this would be to use JsonPath.
A json path of:
$.cityDetails.people
will return just the contents of the people array:
[
[
{
"name": "Foo",
"age": 1
},
{
"name": "Bar",
"age": 2
}
]
]
Here is a Java implementation...

Data Weave Pojo to Pojo Mappings

I am trying to do a Pojo to Pojo transformation as below( each Pojo has a List of objects) - the output is transformed but is skipping an object - sample code below.
public class Pojo1 implements Serializable {
private List<Foo> fooList =new ArrayList<Foo>(1);
public Pojo1() {
}
public List<Foo> getFooList() {
return fooList ;
}
public void setFooList(List<Foo> fooList) {
this.fooList= fooList;
}
}
public class Pojo2 implements Serializable {
private List<Bar> barList =new ArrayList<Bar>(1);
public Pojo2() {
}
public List<Bar> getBarList() {
return barList ;
}
public void setBarList(List<Bar> barList) {
this.barList= barList;
}
}
DataWeave transformation as follows - this works fine but only one object in the List gets transformed and I'm missing the second one.
barList: [{
(
payload.fooList map {
item1:$.item1
}
)
} as :object {
class :"com.fooClass"
}]
} as :object {
class : "com.barClass"
}
Thanks in advance !
Try with
{
barList: in1.fooList map {
item1: $.item1
} as :object {class : "com.fooClass"}
} as :object {class : "com.barClass"}
Note: as :object {class : "com.fooClass"} should be optional, as it can be inferred
The problem seems to be that you defined an array with only one object and filled that object with the result of:
payload.fooList map {
item1:$.item1
}
Which is an array of objects:
[
{
item1: "value1"
},
{
item1: "value2"
}
]
After filling the object with that, it ends up like:
{
item1: "value1",
item1: "value2",
item1: ...
}
So, you are filling the array with an object with a lot of duplicated fields (with different values) and when that output is written (since it's java) each one of those fields only get one value.

How to unwrap single item array and extract value field into one simple field?

I have a JSON document similar to the following:
{
"aaa": [
{
"value": "wewfewfew"
}
],
"bbb": [
{
"value": "wefwefw"
}
]
}
I need to deserialize this into something more clean such as:
public class MyEntity{
private String aaa;
private String bbb;
}
What's the best way to unwrap each array and extract the "value" field on deserialization? Just custom setters? Or is there a nicer way?
For completeness, if you use jackson, you can enable the deserialization feature UNWRAP_SINGLE_VALUE_ARRAYS.
To do that, you have to enable it for the ObjectMapper like so:
ObjectMapper objMapper = new ObjectMapper()
.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
With that, you can just read the class as you are being used to in Jackson.
For example, assuming the class Person:
public class Person {
private String name;
// assume getter, setter et al.
}
and a json personJson:
{
"name" : [
"John Doe"
]
}
We can deserialize it via:
ObjectMapper objMapper = new ObjectMapper()
.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
Person p = objMapper.readValue(personJson, Person.class);
Quick solution with Gson is to use a JsonDeserializer like this:
package stackoverflow.questions.q17853533;
import java.lang.reflect.Type;
import com.google.gson.*;
public class MyEntityDeserializer implements JsonDeserializer<MyEntity> {
public MyEntity deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
String aaa = json.getAsJsonObject().getAsJsonArray("aaa").get(0)
.getAsJsonObject().get("value").getAsString();
String bbb = json.getAsJsonObject().getAsJsonArray("bbb").get(0)
.getAsJsonObject().get("value").getAsString();
return new MyEntity(aaa, bbb);
}
}
and then use it when parsing:
package stackoverflow.questions.q17853533;
import com.google.gson.*;
public class Q17853533 {
public static void main(String[] arg) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(MyEntity.class, new MyEntityDeserializer());
String testString = "{ \"aaa\": [{\"value\": \"wewfewfew\" } ], \"bbb\": [ {\"value\": \"wefwefw\" } ] }";
Gson gson = builder.create();
MyEntity entity= gson.fromJson(testString, MyEntity.class);
System.out.println(entity);
}
}