请记住,JSON结构事先是未知的,即它是完全任意的,我们只知道它是JSON格式。
例如,
以下JSON
{
"Port":
{
"@alias": "defaultHttp",
"Enabled": "true",
"Number": "10092",
"Protocol": "http",
"KeepAliveTimeout": "20000",
"ThreadPool":
{
"@enabled": "false",
"Max": "150",
"ThreadPriority": "5"
},
"ExtendedProperties":
{
"Property":
[
{
"@name": "connectionTimeout",
"$": "20000"
}
]
}
}
}
应该反序列化为具有类似key的类似Map的结构(为简洁起见,不包括以上所有内容):
port[0].alias
port[0].enabled
port[0].extendedProperties.connectionTimeout
port[0].threadPool.max
我目前正在调查杰克逊,所以我们有:
TypeReference<HashMap<String, Object>> typeRef = new TypeReference<HashMap<String, Object>>() {};
Map<String, String> o = objectMapper.readValue(jsonString, typeRef);
但是,生成的Map实例基本上是嵌套Map的Map:
{Port={@alias=diagnostics, Enabled=false, Type=DIAGNOSTIC, Number=10033, Protocol=JDWP, ExtendedProperties={Property={@name=suspend, $=n}}}}
我需要使用“圆点表示法”的扁平化键和扁平化键,如上。
我不希望自己实现此功能,尽管目前我看不到其他任何方式。
您可以执行以下操作遍历树并跟踪找出点表示法属性名称的深度:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.ValueNode;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.junit.Test;
public class FlattenJson {
String json = "{\n" +
" \"Port\":\n" +
" {\n" +
" \"@alias\": \"defaultHttp\",\n" +
" \"Enabled\": \"true\",\n" +
" \"Number\": \"10092\",\n" +
" \"Protocol\": \"http\",\n" +
" \"KeepAliveTimeout\": \"20000\",\n" +
" \"ThreadPool\":\n" +
" {\n" +
" \"@enabled\": \"false\",\n" +
" \"Max\": \"150\",\n" +
" \"ThreadPriority\": \"5\"\n" +
" },\n" +
" \"ExtendedProperties\":\n" +
" {\n" +
" \"Property\":\n" +
" [ \n" +
" {\n" +
" \"@name\": \"connectionTimeout\",\n" +
" \"$\": \"20000\"\n" +
" }\n" +
" ]\n" +
" }\n" +
" }\n" +
"}";
@Test
public void testCreatingKeyValues() {
Map<String, String> map = new HashMap<String, String>();
try {
addKeys("", new ObjectMapper().readTree(json), map);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(map);
}
private void addKeys(String currentPath, JsonNode jsonNode, Map<String, String> map) {
if (jsonNode.isObject()) {
ObjectNode objectNode = (ObjectNode) jsonNode;
Iterator<Map.Entry<String, JsonNode>> iter = objectNode.fields();
String pathPrefix = currentPath.isEmpty() ? "" : currentPath + ".";
while (iter.hasNext()) {
Map.Entry<String, JsonNode> entry = iter.next();
addKeys(pathPrefix + entry.getKey(), entry.getValue(), map);
}
} else if (jsonNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) jsonNode;
for (int i = 0; i < arrayNode.size(); i++) {
addKeys(currentPath + "[" + i + "]", arrayNode.get(i), map);
}
} else if (jsonNode.isValueNode()) {
ValueNode valueNode = (ValueNode) jsonNode;
map.put(currentPath, valueNode.asText());
}
}
}
它产生以下图:
Port.ThreadPool.Max=150,
Port.ThreadPool.@enabled=false,
Port.Number=10092,
Port.ExtendedProperties.Property[0].@name=connectionTimeout,
Port.ThreadPool.ThreadPriority=5,
Port.Protocol=http,
Port.KeepAliveTimeout=20000,
Port.ExtendedProperties.Property[0].$=20000,
Port.@alias=defaultHttp,
Port.Enabled=true
尽管您说JSON是任意的,但最终可能会导致键名冲突,因此剥离@
和$
属性名应该足够容易。
问题内容: 我在这里发现了同样的问题… …但是没有正确的答案。 最好的建议之一是将嵌套对象包装到新类中,但是这种方法引入了另一个问题:乐高名称。 在我的示例中,此类的最逻辑名称是与父类相同的名称,当然这是不可能的。我的示例很简单,我只想消除父类中的“语言”属性。有人可以帮我做吗? json的示例: 问题答案: 如果JSON属性名称与c#命名约定冲突,则可以在序列化期间使用或批注替换其他名称。 例如
我有一个通过RabbitMQ作为消息发送的类,在sender服务上,它的定义如下: 并且在接收方服务上: 在receiver controller中,我有以下方法,它应该接受该消息,将其转换为一个对象,并将其保存在数据库中,看起来如下所示: 编辑:根据请求添加堆栈跟踪。
有人能帮助我,我如何反序列化下面的JSON,我不能改变?我正在使用Jackson进行序列化。 列可以具有未知数量的标题及其值,例如,“Header1”用于行数组中。 到目前为止,我有以下结构: 问题是当我反序列化成QueryResult时映射是空的;我了解TypeReference,但不知道如何指定TypeReference 编辑: 我的对象映射器代码如下: queryResultString的内
问题内容: 我有一个Cabin类,其中包含Row对象的列表。我想像这样序列化对象,但是在反序列化时,我希望Row对象是从Row对象继承的RowRule对象。下面是我一直在尝试的一些示例代码。 问题答案: 简单的答案是使用a 并从返回a : 但是,使用意味着您的JSON中可能存在多态属性。不幸的是,忽略了这些属性。因此,有必要做一些额外的工作并创建: 然后像这样使用它: 原型小提琴。 最后,在使用时
问题内容: 刚刚下载了ServiceStack.Text以在我的ASP.NET中使用它。我有很多属性的类,想将其中的五个(字符串,整数,二进制)序列化为JSON。有人可以发布简单的示例如何从我的课程中创建JSon对象吗? 问题答案: 默认情况下,ServiceStack将反序列化POCO的所有公共属性。 如果只想序列化一些属性,则想用[DataContract],[DataMember]属性装饰类
我需要序列化的类: 我的产品详细信息。java类: 默认序列化输出: 我试图获得的输出: 换句话说,我试图跳过产品列表的JSON括号,并在ProductId和ProductName字段的后面加上一个递增的整数。 非常感谢您的帮助!