如何使用Camel和Jackson库将嵌套的键,值对编组到JSON中?

我有一个Java项目,它当前将一个映射返回给Camel,没有任何嵌套的键,值对,并且Jackson库使用Jackson库将它编组到JSON中。

例如,如果我将以下两个键值放入demoMap中:

Map demoMap = new TreeMap demoMap.put("key1","5"); demoMap.put("key2","10"); 

我得到以下JSON:

 {"key1":"5","key2":"10"} 

但是,现在我的一些键值条目将具有可选的可见性,我需要将其作为嵌套键值放在我的地图中。 任何没有可选可见性的键值都将使用默认值。 所以,例如,如果我为key1和key2指定了可见性,而不是key3,我希望得到JSON,如下所示:

 {"key1":"5", "key2":"10", "key3":"17", "visibility" : { "key1": "a&b&!c", "key2": "a&b", "_default": "a" } } 

如何让Camel使用嵌套键,值对来编组Java对象? 我是一个视觉学习者,所以一个简单的例子会有所帮助。

我尝试更改我的Map以将值作为对象,即:

 Map demoMap = new TreeMap 

然后尝试使用http://examples.javacodegeeks.com/core-java/json/jackson/convert-java-map-to-from-json-using-jackson-example为ArrayList添加一些键的嵌套键值/供参考,但意识到这只是给了我一堆键下的嵌套值,而不是一堆嵌套键,值对。

即使我尝试使用grins,我也遇到了一个来自Camel处理器的错误,其中包含java.lang.ClassCastException,声明java.util.ArrayList无法转换为java.lang.String

同样,当我尝试在我的demoMap中嵌套Map时,我得到了这个ClassCastException:

 3244 [hello.world.request.timer] ERROR org.apache.camel.processor.DefaultErrorHandler - Failed delivery for exchangeId: e6518e39-89b7-435e-96d9-ce26811ac67e. Exhausted after delivery attempt: 1 caught: java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.String 

所以我知道怎么不这样做。 : – /

我在http://camel.apache.org/json.html上重新阅读了Camel JSON文档,但在撰写本文时,它没有指定嵌套键值对的示例。

更新:根据汤姆的反馈我创建了两个地图即,

 Map keyvalues = new TreeMap(); Map visibility = new TreeMap(); 

这是我的类,我称之为SensorGenerator,它将属性文件加载到Map中:

 package sample; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import org.codehaus.jackson.annotate.JsonAnyGetter; import org.codehaus.jackson.annotate.JsonProperty; public class SensorGenerator { private Properties sourceProperties; // create a map of sensor keyvalues, and a map of sensor visibility Map keyvalues = new TreeMap(); @JsonProperty Map visibility = new TreeMap(); @JsonAnyGetter public Map getKeyvalues() { for (Object key : sourceProperties.keySet()) { // Separate out each of the field:datatype:visibility tuples as an entry in the // values array String[] values = sourceProperties.getProperty((String) key).split( ","); // split the key between 'sensor' and the 'number' Ex: sensor1 -> sensor,1 String[] keyArray = key.toString().split("(?<=([a-zA-Z]++))"); String keyNumber = keyArray[1]; // grab the number to append for each sensor // define string buffer that appends sensor number for each sensor's // keys. Ex: sensor1 would have s1make, s1makeDataType, etc. StringBuffer sensorNumberStringBuffer = new StringBuffer(); sensorNumberStringBuffer.append("s"); sensorNumberStringBuffer.append(keyNumber); // make, its data type, and visibility (with s# prefix) StringBuffer makeStringBuffer = new StringBuffer(); makeStringBuffer.append(sensorNumberStringBuffer); makeStringBuffer.append("make"); StringBuffer makeDataTypeStringBuffer = new StringBuffer(); makeDataTypeStringBuffer.append(sensorNumberStringBuffer); makeDataTypeStringBuffer.append("makeDataType"); StringBuffer makeVizStringBuffer = new StringBuffer(); makeVizStringBuffer.append(sensorNumberStringBuffer); makeVizStringBuffer.append("makeViz"); // model, its data type, and visibility (with s# prefix) StringBuffer modelStringBuffer = new StringBuffer(); modelStringBuffer.append(sensorNumberStringBuffer); modelStringBuffer.append("model"); StringBuffer modelDataTypeStringBuffer = new StringBuffer(); modelDataTypeStringBuffer.append(sensorNumberStringBuffer); modelDataTypeStringBuffer.append("modelDataType"); StringBuffer modelVizStringBuffer = new StringBuffer(); modelVizStringBuffer.append(sensorNumberStringBuffer); modelVizStringBuffer.append("modelViz"); // serialNumber, its data type, and visibility (with s# prefix) StringBuffer serialNumberStringBuffer = new StringBuffer(); serialNumberStringBuffer.append(sensorNumberStringBuffer); serialNumberStringBuffer.append("serialNumber"); StringBuffer serialNumberDataTypeStringBuffer = new StringBuffer(); serialNumberDataTypeStringBuffer.append(sensorNumberStringBuffer); serialNumberDataTypeStringBuffer.append("serialNumberDataType"); StringBuffer serialNumberVizStringBuffer = new StringBuffer(); serialNumberVizStringBuffer.append(sensorNumberStringBuffer); serialNumberVizStringBuffer.append("serialNumberViz"); // sensorType, its data type, and visibility (with s# prefix) StringBuffer sensorTypeStringBuffer = new StringBuffer(); sensorTypeStringBuffer.append(sensorNumberStringBuffer); sensorTypeStringBuffer.append("sensorType"); StringBuffer sensorTypeDataTypeStringBuffer = new StringBuffer(); sensorTypeDataTypeStringBuffer.append(sensorNumberStringBuffer); sensorTypeDataTypeStringBuffer.append("sensorTypeDataType"); StringBuffer sensorTypeVizStringBuffer = new StringBuffer(); sensorTypeVizStringBuffer.append(sensorNumberStringBuffer); sensorTypeVizStringBuffer.append("sensorTypeViz"); // put all the field:datatype keyvalues for this sensor in the keyvalues map // and visibilities in the visibility map // make, data type, and visibility keyvalues.put(makeStringBuffer.toString(), values[0].split(":")[0]); keyvalues.put(makeDataTypeStringBuffer.toString(), values[0].split(":")[1]); visibility.put(makeVizStringBuffer.toString(), values[0].split(":")[2]); // model, data type, and visibility keyvalues.put(modelStringBuffer.toString(), values[1].split(":")[0]); keyvalues.put(modelDataTypeStringBuffer.toString(), values[1].split(":")[1]); visibility.put(modelVizStringBuffer.toString(), values[1].split(":")[2]); // serialNumber, data type, and visibility keyvalues.put(serialNumberStringBuffer.toString(), values[2].split(":")[0]); keyvalues.put(serialNumberDataTypeStringBuffer.toString(), values[2].split(":")[1]); visibility.put(serialNumberVizStringBuffer.toString(), values[2].split(":")[2]); // sensorType, data type, and visibility keyvalues.put(sensorTypeStringBuffer.toString(), values[3].split(":")[0]); keyvalues.put(sensorTypeDataTypeStringBuffer.toString(), values[3].split(":")[1]); visibility.put(sensorTypeVizStringBuffer.toString(), values[3].split(":")[2]); // add in default visibility visibility.put("_default", "a"); } return keyvalues; } public void setSourceProperties(Properties properties) { this.sourceProperties = properties; } } 

现在我只是将默认可见性硬编码为“a”,但稍后会将其更改为也从属性文件中提取。

您的结构不仅仅是一张地图。 这是两个不同序列化的地图。 表示这一点的一种方法是:

 public class Whatever{ Map keyvalues; Map visibility; } 

你最终得到的是这个,虽然代表数据远非理想:

 { "keyvalues" : { "key1": "5", "key2": "10", "key3": "17"}, "visibility" : { "key1": "a&b&!c", "key2": "a&b", "_default": "a" } } 

要获得所需内容,请使用@JsonAnyGetter。 像这样的东西(它可以更容易使用):

 public class Whatever{ Map keyvalues = new TreeMap(); @JsonProperty Map visibility = new TreeMap(); @JsonAnyGetter public Map getKeyvalues() { return keyvalues; } } 

产生:

  {"visibility":{"key1":"a&b&!c","key2":"a&b"},"key1":"5","key2":"10"} 

我今天一直在与这个斗争,你的问题激励我做出血腥的工作:D注释在这里: https : //github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations

请参阅此处的JUnit测试: https : //gist.github.com/TomDemeranville/7009250