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
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)
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.
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...
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.
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);
}
}