I'm trying to reproduce this article so I can load configs from a json file within the app's folder. But there appears to be some issue with the binding to the properties class. When I inspect the nested config I don't see the arrays of objects I'd expect, but an array of LinkedHashMaps.
Any ideas to accomplish this?
Debugging:
DemoBotApplication.java:
package com.myapp.demo;
#SpringBootApplication
#ComponentScan(basePackageClasses = {JsonProperties.class})
public class DemoBotApplication {
#Autowired
private TestService test;
public static void main(String[] args) {
new SpringApplicationBuilder(DemoBotApplication.class).initializers(new JsonPropertyContextInitializer()).run();
}
#PostConstruct
public void init() {
test.test();
}
}
TestService.java:
#Service
public class TestService {
#Autowired
private BotConfig botConfig;
public void test() {
List<com.myapp.demo.config.BotConfig.Device> devices = botConfig.getDevices();
}
}
JsonProperties.java:
package com.myapp.demo.config;
#Configuration
#ConfigurationProperties(prefix = "json")
#Data
public class JsonProperties {
private String serverUrl;
private List<Device> devices;
#Data
public static class Device {
private int id;
private int period;
private float step;
private List<Waypoint> waypoints;
#Data
public static class Waypoint {
private double latitude;
private double longitude;
}
}
}
JsonPropertyContextInitializer.java:
package com.myapp.demo.config;
public class JsonPropertyContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private final static String JSON_PREFIX = "json";
#Override
#SuppressWarnings("unchecked")
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
try {
Resource resource = configurableApplicationContext.getResource("file:./config.json");
Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class);
Set<Map.Entry> set = readValue.entrySet();
List<MapPropertySource> propertySources = convertEntrySet(set, Optional.empty());
for (PropertySource propertySource : propertySources) {
configurableApplicationContext.getEnvironment().getPropertySources().addFirst(propertySource);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static List<MapPropertySource> convertEntrySet(Set<Map.Entry> entrySet, Optional<String> parentKey) {
return entrySet.stream().map((Map.Entry e) -> convertToPropertySourceList(e, parentKey))
.flatMap(Collection::stream).collect(Collectors.toList());
}
private static List<MapPropertySource> convertToPropertySourceList(Map.Entry entry, Optional<String> parentKey) {
String key = parentKey.map(s -> s + ".").orElse("") + (String) entry.getKey();
Object value = entry.getValue();
return convertToPropertySourceList(key, value);
}
#SuppressWarnings("unchecked")
private static List<MapPropertySource> convertToPropertySourceList(String key, Object value) {
// handles arrays
if (value instanceof ArrayList) {
ArrayList list = (ArrayList) value;
List<MapPropertySource> converted = new ArrayList<MapPropertySource>();
for (int i = 0; i < list.size(); i++) {
LinkedHashMap map = (LinkedHashMap) list.get(i);
Set<Map.Entry> entrySet = map.entrySet();
String arrayKey = String.format("%s[%d]", key, i);
converted.addAll(convertEntrySet(entrySet, Optional.ofNullable(arrayKey)));
}
return converted;
}
// handles nested objects
if (value instanceof LinkedHashMap) {
LinkedHashMap map = (LinkedHashMap) value;
Set<Map.Entry> entrySet = map.entrySet();
return convertEntrySet(entrySet, Optional.ofNullable(key));
}
String finalKey = String.format("%s.%s", JSON_PREFIX, key);
return Collections.singletonList(new MapPropertySource(finalKey, Collections.singletonMap(finalKey, value)));
}
}
config.json:
{
"serverUrl": "localhost:5093",
"devices": [
{
"id": "123456789",
"period": 5,
"step": 0.001,
"speed": 40,
"waypoints": [
{
"latitude": 48.8537,
"longitude": 2.344347
},
{
"latitude": 48.855235,
"longitude": 2.345852
},
{
"latitude": 48.857238,
"longitude": 2.347153
},
{
"latitude": 48.858509,
"longitude": 2.342563
},
{
"latitude": 48.856066,
"longitude": 2.340432
},
{
"latitude": 48.85478,
"longitude": 2.34223
}
]
}
]
}
Related
Can somebody help me, how I can deserialize the following JSON, which I can not change?
I am using Jackson for serialization.
{
"columns": [
{
"header": "Heading1",
},
{
"header": "Heading2",
}
],
"rows": [
"id": 1,
"Heading1": {
"value": "Value1"
},
"Heading2": {
"value": "Value2"
}
]
}
Columns can have unknown number of headers and their value eg. "Header1" is used in the rows array.
So far I have the following structure:
public class QueryResult {
private ColumnConfig[] columns;
private QueryResultRow[] rows;
}
public class ColumnConfig {
private String header;
}
public class QueryResultRow {
private int id;
private Map<String, CellValue> values;
}
public class CellValue{
private String value;
}
The problem is that the Map is empty when I deserialize into QueryResult;
I read about TypeReference but I do not know how I can specify a TypeReference<HashMap<String,CellValue>> for the property values in QueryResultRow.
Edit:
My ObjectMapper code is the following:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String queryResultString = loadQuery(queryPath);
QueryResult result = mapper.readValue(queryResultString, QueryResult.class);
The content of queryResultString is the JSON above.
First problem is your JSON is invalid. I assume it should be something like this,
{
"columns": [
{
"header": "Heading1"
},
{
"header": "Heading2"
}
],
"rows": [
{
"id": 1,
"Heading1": {
"value": "Value1"
},
"Heading2": {
"value": "Value2"
}
}
]
}
Then answer is quite straightforward. You need to change your QueryResultRow as follows,
class QueryResultRow {
private int id;
private Map<String, CellValue> values = new HashMap<>();
#JsonAnySetter
public void addValues(String k, CellValue v) {
values.put(k, v);
}
}
Then I think you should good to go.
Here is a complete working example,
public class Main {
public static void main(String[] args) throws IOException {
String s = "{\"columns\":[{\"header\":\"Heading1\"},{\"header\":\"Heading2\"}],\"rows\":[{\"id\":1,\"Heading1\":{\"value\":\"Value1\"},\"Heading2\":{\"value\":\"Value2\"}}]}";
ObjectMapper om = new ObjectMapper();
QueryResult queryResult = om.readValue(s, QueryResult.class);
System.out.println(queryResult);
}
}
#Getter
#Setter
#ToString
class QueryResult {
private ColumnConfig[] columns;
private QueryResultRow[] rows;
}
#Getter
#Setter
#ToString
class ColumnConfig {
private String header;
}
#Getter
#Setter
#ToString
class QueryResultRow {
private int id;
private Map<String, CellValue> values = new HashMap<>();
#JsonAnySetter
public void addValues(String k, CellValue v) {
values.put(k, v);
}
}
#Getter
#Setter
#ToString
class CellValue{
private String value;
}
I have a complex nested Json
It has a body similar to this:
{
staus: "Success",
id: 1,
data: [{'Movie':'kung fu panda','% viewed': 50.5},{'Movie':'kung fu panda 2','% viewed':1.5}],
metadata: {'filters':['Movie', 'Percentage Viewed'], 'params':{'content':'Comedy', 'type': 'Movie'}}
}
The only field I care about is data, and metadata is usually an even more complex/nested field. I was trying to map this to:
#JsonIgnoreProperties(ignoreUnknown = true)
class ResponseData{
public Data[] data;
#JsonIgnoreProperties(ignoreUnknown = true)
class Data{
public String Movie;
public double viewed;
}
}
I was looking at Jackson as an option and writing my own serializer and use JsonIgnore to discard the metadata but can't get around it.
Any suggestion on how this could be done?
You can use jackson-utils
public class Foo {
public static void main(String... args) {
ResponseData responseData1 = new ResponseData(
1,
"Success",
new ResponseData.Data[] {
new ResponseData.Data("kung fu panda", 50.5),
new ResponseData.Data("kung fu panda 2", 1.5) },
new ResponseData.Metadata(
new HashSet<>(Arrays.asList("Movie", "Percentage Viewed")),
new ResponseData.Metadata.Params("Comedy", "Movie"))
);
String json = JacksonUtils.prettyPrint().writeValue(responseData1);
System.out.println(json);
ResponseData responseData2 = JacksonUtils.readValue(json, ResponseData.class);
}
}
class ResponseData {
private int id;
private String status;
private Data[] data;
private Metadata metadata;
public ResponseData() {
}
public ResponseData(int id, String status, Data[] data, Metadata metadata) {
this.id = id;
this.status = status;
this.data = data;
this.metadata = metadata;
}
public static class Data {
#JsonProperty("Movie")
private String movie;
#JsonProperty("% viewed")
private double viewedPercents;
public Data() {
}
public Data(String movie, double viewedPercents) {
this.movie = movie;
this.viewedPercents = viewedPercents;
}
}
public static class Metadata {
private Set<String> filters;
private Params params;
public Metadata() {
}
public Metadata(Set<String> filters, Params params) {
this.filters = filters;
this.params = params;
}
public static class Params {
private String content;
private String type;
public Params() {
}
public Params(String content, String type) {
this.content = content;
this.type = type;
}
}
}
}
Console output:
{
"id" : 1,
"status" : "Success",
"data" : [ {
"Movie" : "kung fu panda",
"% viewed" : 50.5
}, {
"Movie" : "kung fu panda 2",
"% viewed" : 1.5
} ],
"metadata" : {
"filters" : [ "Movie", "Percentage Viewed" ],
"params" : {
"content" : "Comedy",
"type" : "Movie"
}
}
}
P.S. As an alternative, there is another util gson-utils with the same syntax.
I've got a JSON input like this
{
"slices": [{
"slice": {
"boundedBy": {
"Envelope": {
"axisLabels": "Lat Long ansi",
"lowerCorner": "-44.975 111.975 \"2003-01-01T00:00:00+00:00\"",
"upperCorner": "-8.975 155.975 \"2003-01-01T00:00:00+00:00\"",
"srsDimension": 3
}
},
"fileReferenceHistory": "/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20030101-20030110-H01V06-1.0_MERIS-FR-LAI-HA.tiff",
"local_metadata_key": "value_1"
}
},
{
"slice": {
"boundedBy": {
"Envelope": {
"axisLabels": "Lat Long ansi",
"lowerCorner": "-44.975 111.975 \"2003-10-01T00:00:00+00:00\"",
"upperCorner": "-8.975 155.975 \"2003-10-01T00:00:00+00:00\"",
"srsDimension": 3
}
},
"fileReferenceHistory": "/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20031001-20031010-H00V10-1.0_MERIS-FR-LAI-HA.tiff",
"local_metadata_key": "value_2"
}
}
],
"Title": "Drought code",
// other keys:values
}
with "slices" is an array of "slice" objects. Out of "slices" is any "keys":"values" but it is not the problem.
Then, I have a POJO class
public class CoverageMetadata {
#JsonProperty(value = "slices")
#JacksonXmlElementWrapper(useWrapping = false)
private List<LocalMetadata> localMetadataList;
private Map<String, String> globalMetadataAttributesMap;
#JsonAnySetter
public void addKeyValue(String key, String value) {
this.globalMetadataAttributesMap.put(key, value);
}
#JsonAnyGetter
public Map<String, String> getGlobalAttributesMap() {
return globalMetadataAttributesMap;
}
// other gettters, setters without Jackson annotations
}
and a class inside the list:
public class LocalMetadata {
public static final String LOCAL_METADATA_TAG = "slice";
private Map<String, String> localMetadataAttributesMap;
private BoundedBy boundedBy;
#JsonAnySetter
// NOTE: To map an unknown list of properties, must use this annotation
public void addKeyValue(String key, String value) {
this.localMetadataAttributesMap.put(key, value);
}
public LocalMetadata() {
this.localMetadataAttributesMap = new LinkedHashMap<>();
this.boundedBy = new BoundedBy();
}
#JsonAnyGetter
// NOTE: to unwrap the "map" from { "map": { "key": "value" } }, only keep { "key": "value" }
public Map<String, String> getLocalMetadataAttributesMap() {
return localMetadataAttributesMap;
}
public BoundedBy getBoundedBy() {
return this.boundedBy;
}
public void setBoundedBy(BoundedBy boundedBy) {
this.boundedBy = boundedBy;
}
public LocalMetadata(Map<String, String> localMetadataAttributesMap, BoundedBy boundedBy) {
this.localMetadataAttributesMap = localMetadataAttributesMap;
this.boundedBy = boundedBy;
}
}
And the basic code to deserialize JSON to object
ObjectMapper objectMapper = new ObjectMapper();
CoveageMetadata coverageMetadata = objectMapper.readValue(metadata, CoverageMetadata.class);
When I try to deserialize the JSON input to CoverageMetadata object, I got the error
Cannot deserialize coverage's metadata in XML/JSON by Jackson, error: Can not deserialize instance of java.lang.String out of START_OBJECT token
at [Source: {"slices":[{"slice":{"boundedBy":{"Envelope":{"axisLabels":"Lat Long ansi","srsDimension":3,"lowerCorner":"-44.975 111.975 \"2003-01-01T00:00:00+00:00\"","upperCorner":"-8.975 155.975 \"2003-01-01T00:00:00+00:00\""}},"local_metadata_key":"value_1","fileReferenceHistory":"/home/rasdaman/rasdaman_community/rasdaman/systemtest/testcases_services/test_all_wcst_import/testdata/wcs_local_metadata_tiff_no_specify_bands/GlobLAI-20030101-20030110-H01V06-1.0_MERIS-FR-LAI-HA.tiff"}}],"Title":"Drought code"}; line: 1, column: 21] (through reference chain: petascope.core.gml.metadata.model.CoverageMetadata["slices"]->java.util.ArrayList[0]->petascope.core.gml.metadata.model.LocalMetadata["slice"]).
How can I deserialize this JSON input String to CoverageMetadataObject with each "slice" element will be mapped to a LocalMetadata object?
The simple answer is I create another POJO class to hold the "slices" list, in CoverageMetadata class, it will have
public class CoverageMetadata {
private Map<String, String> globalMetadataAttributesMap;
#JsonProperty(value = "slices")
private LocalMetadata localMetadata;
...
}
New POJO class (class LocalMetadata before was renamed to LocalMetadataChild)
public class LocalMetadata {
#JsonProperty(value = "slice")
// This is the most important thing to avoid duplicate <slices><slices> when serializing in XML.
#JacksonXmlElementWrapper(useWrapping = false)
private List<LocalMetadataChild> localMetadataList;
public LocalMetadata(List<LocalMetadataChild> localMetadataList) {
this.localMetadataList = localMetadataList;
}
public LocalMetadata() {
this.localMetadataList = new ArrayList<>();
}
public List<LocalMetadataChild> getLocalMetadataList() {
return localMetadataList;
}
public void setLocalMetadataList(List<LocalMetadataChild> localMetadataList) {
this.localMetadataList = localMetadataList;
}
}
Working on building the model for an application dealing with physical buildings.
Ideally, we'd want something like this:
City has multiple Offices, which have multiple Rooms, which have properties.
We're using jackson to parse the JSON payload received from the API datasource, and it ends up looking a bit differently than the examples I've seen.
The format we're getting is:
{
"CityName1":
{ "OfficeName1":
[
{"name": RoomName1, "RoomProperty2": RoomValue1},
{"name": RoomName2, "RoomProperty2": RoomValue2}
]
},
{ "OfficeName2": [{...}]},
{ "OfficeNameX" : [{...}] },
"CityName2": {...},
"CityNameN": {...}}
Java classes:
public class City {
private Map<String, Object> additionalProperties = new HashMap<String, Object();
private List<Office> _offices = new ArrayList<Office>();
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value)
throws IOException {
_cityName = name;
String officeJson = _mapper.writeValueAsString(value);
StringBuilder sb = new StringBuilder(officeJson);
_offices.add(_mapper.readValue(officeJson, Office.class));
this.additionalProperties.put(name, value);
}
}
public class Office {
private String _officeName;
private static final ObjectMapper _mapper = new ObjectMapper();
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
private List<Room> _rooms = new ArrayList<Room>();
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value)
throws IOException {
_officeName = name;
String roomJson = _mapper.writeValueAsString(value);
Room[] rooms = _mapper.readValue(roomJson, Room[].class);
_rooms.addAll(Arrays.asList(rooms));
this.additionalProperties.put(name, value);
}
public List<Room> getRooms() {
return _rooms;
}
public void setRooms(List<Room> rooms) {
_rooms = rooms;
}
}
public class Room {
private static final String NAME = "name";
private static final String PROP_2 = "RoomProperty2";
#JsonProperty(PROP_2)
private String _propertyTwo;
#JsonProperty(NAME)
private String name;
#JsonProperty(PROP_2)
public String getPropertyTwo() {
return _propertyTwo;
}
#JsonProperty(PROP_2)
public void setPropertyTwo(String propTwo) {
_propertyTwo = propTwo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
So how would I go about parsing this with jackson ? Currently, I am using an #JsonAnySetter to grab the name, and saving that as the city or office name and then sending the value sent to JsonAnySetter to the appropriate nested class. The real issue comes with getting a list of Offices in the City. When using a mapper.readvalues(String, Office.class), I get returned an iterator of only the last office for each city. Any ideas guys?
Sorry if that seemed confusing! Would love to answer any questions I've created.
Thanks for the help!
I think the best solution is to write your own deserialiser here since your JSON document doesn't really map well to the class structure you want.
The solution below reads each city as a Map<String, List<Room>> and the collection of cities as a Map<String, City> and then create City and Office objects from these inside the deserialisers.
Room.java is the same as yours, here are the rest:
Cities.java:
#JsonDeserialize(using=CitiesDeserializer.class)
public class Cities implements Iterable<City> {
private final List<City> cities;
public Cities(final List<City> cities) {
this.cities = cities;
}
public Cities() {
this.cities = new ArrayList<>();
}
public List<City> getCities() {
return cities;
}
#Override
public Iterator<City> iterator() {
return cities.iterator();
}
}
CitiesDeserialiser.java:
public class CitiesDeserializer extends JsonDeserializer<Cities> {
private static final TypeReference<Map<String, City>> TYPE_REFERENCE = new TypeReference<Map<String, City>>() {};
#Override
public Cities deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
final Map<String, City> map = jp.readValueAs(TYPE_REFERENCE);
List<City> cities = new ArrayList<>();
for(Map.Entry<String, City> entry : map.entrySet()) {
City city = entry.getValue();
city.setName(entry.getKey());
cities.add(city);
}
return new Cities(cities);
}
}
City.java:
#JsonDeserialize(using=CityDeserialzer.class)
public class City {
private String name;
private List<Office> offices;
// Setters and getters
}
CityDeserializer.java:
public class CityDeserialzer extends JsonDeserializer<City> {
private static final TypeReference<Map<String, List<Room>>> TYPE_REFERENCE = new TypeReference<Map<String, List<Room>>>() {};
#Override
public City deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
final Map<String, List<Room>> map = jp.readValueAs(TYPE_REFERENCE);
List<Office> offices = new ArrayList<>();
for(Map.Entry<String, List<Room>> entry : map.entrySet()) {
Office office = new Office();
office.setName(entry.getKey());
office.setRooms(entry.getValue());
offices.add(office);
}
City city = new City();
city.setOffices(offices);
return city;
}
}
Office.java:
public class Office {
private String name;
private List<Room> rooms;
// Setters and getters
}
And here's a test to show that it works:
JSON:
{
"CityName1": {
"OfficeName1": [ {
"name": "RoomName1",
"RoomProperty2": "RoomValue1"
}, {
"name": "RoomName2",
"RoomProperty2": "RoomValue2"
} ],
"OfficeName2": [ {
"name": "RoomName3",
"RoomProperty2": "RoomValue3"
}, {
"name": "RoomName4",
"RoomProperty2": "RoomValue4"
} ]
},
"CityName2": {
"OfficeName3": [ {
"name": "RoomName5",
"RoomProperty2": "RoomValue5"
}, {
"name": "RoomName6",
"RoomProperty2": "RoomValue6"
} ],
"OfficeName4": [ {
"name": "RoomName7",
"RoomProperty2": "RoomValue7"
}, {
"name": "RoomName8",
"RoomProperty2": "RoomValue8"
} ]
}
}
Test.java:
public class Test {
public static void main(String[] args) {
String json = ...
ObjectMapper mapper = new ObjectMapper();
Cities cities = mapper.readValue(json, Cities.class);
for(City city : cities) {
System.out.println(city.getName());
for(Office office : city.getOffices()) {
System.out.println("\t" + office.getName());
for(Room room : office.getRooms()) {
System.out.println("\t\t" + room.getName());
System.out.println("\t\t\t" + room.getPropertyTwo());
}
}
}
}
}
Output:
CityName1
OfficeName1
RoomName1
RoomValue1
RoomName2
RoomValue2
OfficeName2
RoomName3
RoomValue3
RoomName4
RoomValue4
CityName2
OfficeName3
RoomName5
RoomValue5
RoomName6
RoomValue6
OfficeName4
RoomName7
RoomValue7
RoomName8
RoomValue8
I have a JSON string like:
"shipping_profiles": {
"563": {
"name": "name",
"value": "value"
},
"564": {
"name": "name",
"value": "value"
},
"565": {
"name": "name",
"value": "value"
},
"566": {
"name": "name",
"value": "value"
}
}
Now I am parsing it with Jackson 2.0.
I am trying to get a List<shipping_profiles> from the JSON string.
Is it possible?
Your shipping_profiles property doesn't look like array. It represent object with dynamic properties, so we should treat it like an object. If we do not know anything about properties we can use #JsonAnySetter annotation. Algorithm could looks like below:
Deserialize JSON into JSON-model classes.
Convert dynamic objects (maps) into app's POJO classes using ObjectMapper
Use app's POJO whenever you want.
Please see my example implementation. I hope, it help you solve your problem. Input JSON:
{
"shipping_profiles":{
"563":{
"name":"name563",
"value":"value563"
},
"564":{
"name":"name564",
"value":"value564"
},
"565":{
"name":"name565",
"value":"value565"
},
"566":{
"name":"name566",
"value":"value566"
}
}
}
Example program:
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonProgram {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
File source = new File("X:/test.json");
Entity entity = mapper.readValue(source, Entity.class);
ShippingProfiles shippingProfiles = entity.getShippingProfiles();
List<Map<String, String>> profileMaps = shippingProfiles.getProfiles();
List<Profile> profiles = new ArrayList<Profile>(profileMaps.size());
for (Map<String, String> item : profileMaps) {
profiles.add(mapper.convertValue(item, Profile.class));
}
System.out.println(profiles);
}
}
class Entity {
#JsonProperty("shipping_profiles")
private ShippingProfiles shippingProfiles;
public ShippingProfiles getShippingProfiles() {
return shippingProfiles;
}
public void setShippingProfiles(ShippingProfiles shippingProfiles) {
this.shippingProfiles = shippingProfiles;
}
}
class ShippingProfiles {
private List<Map<String, String>> profiles = new ArrayList<Map<String, String>>();
#JsonAnySetter
public void setDynamicProperty(String name, Map<String, String> map) {
profiles.add(map);
}
public List<Map<String, String>> getProfiles() {
return profiles;
}
public void setProfiles(List<Map<String, String>> profiles) {
this.profiles = profiles;
}
}
class Profile {
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString() {
return "Profile [name=" + name + ", value=" + value + "]";
}
}
Above app prints:
[Profile [name=name563, value=value563], Profile [name=name564, value=value564], Profile [name=name565, value=value565], Profile [name=name566, value=value566]]
I got my json with dynamic property parsed with the way #michalziober provide.
"commandClasses": {
"32": {
"name": "Basic",
"data": {
"name": "devices.1.instances.1.commandClasses.32.data",
"value": null,
"type": "NoneType"
},
"38": {
"name": "SwitchMultilevel",
"data": {
"name": "devices.1.instances.1.commandClasses.38.data",
"value": null,
"type": "NoneType"
},
"43": {
"name": "SceneActivation",
"data": {
"name": "devices.1.instances.1.commandClasses.43.data",
"value": null,
"type": "NoneType"
}
With this json I also need to save that dynamic property, so I add another List for storing it.
public class CommandClasses {
private List<String> nameList = new ArrayList<String>();
private List<CommandClass> commmandClasses = new ArrayList<CommandClass>();
private Logger logger = Logger.getInstance(CommandClasses.class);
#JsonAnySetter
public void setDynamicCommandClass(String name, CommandClass cc) {
logger.d("# adding new CC : " + name);
nameList.add(name);
commmandClasses.add(cc);
}
public List<CommandClass> getCommmandClasses() {
return commmandClasses;
}
public void setCommmandClasses(List<CommandClass> commmandClasses) {
this.commmandClasses = commmandClasses;
}
}
Now I can also access the field as id to send out request later.