json 协议有规定连续两次序列化一个对象应该怎么样吗?
json 协议有规定连续两次序列化一个对象应该怎么样吗?
子问题:
- python 如果反序列化一个「连续两次序列化后的字符串」
- java 如果反序列化一个「连续两次序列化后的字符串」
有一个 python 的 dict
content = { 'name': '你好'
}
我调用两次 json.dumps()
import jsoncontent = {
'name': '你好'
}
print(json.dumps(json.dumps(content)))
输出如下
"{\"name\": \"\\u4f60\\u597d\"}"
然后我调用两次 json.loads,这个「被连续两次序列化后的字符串」就会变回 dict
import jsoncontent = {
'name': '你好'
}
print(json.dumps(json.dumps(content)))
a = json.dumps(json.dumps(content))
print(json.loads(json.loads(a)))
输出如下:
"{\"name\": \"\\u4f60\\u597d\"}"{'name': '你好'}
一切都非常的优雅
但是当我 python 把 "{\"name\": \"\\u4f60\\u597d\"}"
传递给 java 同事的时候,他们告诉我,他们无法「简单」实现「把上面的字符串连续两次反序列化变成一个 hashmap」,他们说如果要反序列化成 hashmap 怎么怎么麻烦
我不理解,这么成熟的编程语言 java 为什么不能简单优雅的实现这一点?
我把这个需求「使用 java 反序列化 "{\"name\": \"\\u4f60\\u597d\"}"
为 hashmap」问 chatGPT,它给的答案也是莫名其妙
为什么?是 java 的问题还是说 json 的协议就对于「连续两次序列化」没有做出标准规定导致不同编程语言自己有自己的实现?
有谁知道,像 golang 和 rust、js 这些语言又是怎么处理这个问题呢?
回答:
一次序列化的结果是 string ,两次序列化不过就是把 string 根据 json 序列化 string 的规则又序列化了一遍。
对于 Java 这一个强类型语言来说,表示 Json 这个各种类型混合的对象本身就是一件很麻烦的事情。所以不论你是一次序列化还是两次,都有很多麻烦事要搞。
回答:
1、一定要序列化两次吗,一次不就是一个 json string了吗?
2、如果一定要序列化两次,那第二次的结果其实就是一个string了,把里面的 \" 全部替换成 ",再解析就可以了
回答:
json 协议有规定连续两次序列化一个对象应该怎么样吗?
没有,也不需要,就是简单的套娃,套娃几次拆几次就回去了
无法「简单」实现「把上面的字符串连续两次反序列化变成一个 hashmap」
不能说很麻烦但是也不简单,起码框架自己没这功能给反序列化两次,但是自己写也就一行的事情
顺便吐槽一句,随便飞 hashmap 的 java 农都应该去写 php
回答:
这不是很简单的问题吗?某些写java的人是不是被spring惯坏了,最基本的代码都不会了
下面是用 gson 实现的一个简单的例子
Gson gson = new Gson();Sring s = gson.fromJson(your_python_dumps_dumps_str, String.class);
TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>(){};
Map<String, String> stringMap = gson.fromJson(s, mapType);
System.out.println(stringMap.get("name"))
如果要转为 data calss User(val name:String)
,只需要把 mapType
换成 User.class
顺便吐槽一下, java 的代码是真的又臭又长,我用 kotlin 写就没那么多冗余代码
回答:
1.对象序列化两次这件事本身很异常,序列化一次之后就是字符串了,不明白为什么还要对字符串序列化
2.这是一个使用FastJson反序列化的例子
public static void main(String[] args) { Object parse = JSON.parse("\"{\\\"name\\\": \\\"\\\\u4f60\\\\u597d\\\"}\"");
Object parse1 = JSON.parse((String) parse);
System.out.println(parse1);
}
该例子中,parse1是JSONObject类型的对象。JSONObject是Map类的一个实现,应该是满足需求的
回答:
首先,我不明白为什么要序列化两次。第一次序列化会得到一个 JSON,这是一个描述了完整结构化数据的字符串。再次序列化其实是获得一个字符串的 JSON,也就是字符串的字符串。
我猜是因为要两次序列化的结果才能直接从控制台拷贝到代码中使用,是个很伤心的理由,希望不是这个原因 ?。
如果只是为了传输用,第一次序列化的结果就已经够用了。对方收到这个字符串之后,直接反序列化就能得到对应的结构化数据。不过既然序列化了两次,对方得到这个数据的时候,也需要反序列化两次,这不找事儿么 ?
然后,不管是哪里生成的 JSON,只有人工拼的比较容易出错,工具处理出来的一般都遵循标准 (json.org)。既然是标准的 JSON,Java 里的 JSON 库都是可以处理的,比如 Jackson、Gson 等库都能处理(实测处理起来有点区别)。
以实例来说,假如有这样一个数据(第一行是第一次序列化的结果,第二行是再次序列化的结果)
{"name":"James","age":20,"money":123.45}"{\"name\":\"James\",\"age\":20,\"money\":123.45}"
生成这两个数据的代码 (Java/Jackson) 如下(不要在意 Person 的结构,就是包含 name、age 和 money 几个属性的对象):
如果要对 json
直接赋值,确实需要转义,拷贝的话需要使用第二个结果。但它的内容实际是第一个结果:
在 Java 中要把这个字符串反序列化成 HashMap,只需要用 json
(第一次序列化结果)就行(以 Jackson 为例)
如果要想从 json2 反序列化出来,需要两次(以 Gson 为例)
提醒一下
这张图和上面那张相比,
age
的类型不一样;Jackson 会根据数值来识别类型为 Integer,但 Gson 直接用的 Double 作为对应于number
的标准类型。两种处理策略各有优劣,自己根据情况来选择吧。
完整的示例代码如下 (Java):
package playground.sf.q1010000044532110;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Map;
public class Solution {
public static void main(String[] args) throws JsonProcessingException {
var objectMapper = new ObjectMapper();
var json = objectMapper.writeValueAsString(new Person("James"));
// String json = "{\"name\":\"James\",\"age\":20,\"money\":123.45}";
System.out.println(json);
var json2 = objectMapper.writeValueAsString(json);
System.out.println(json2);
HashMap<String, Object> map1 = objectMapper.readValue(json, HashMap.class);
System.out.println(map1);
dumpMap(map1);
Gson gson = new Gson();
var gotJson = gson.fromJson(json2, String.class);
System.out.println(gotJson);
HashMap<String, Object> map2 = gson.fromJson(gotJson, HashMap.class);
System.out.println(map2);
dumpMap(map2);
}
static void dumpMap(@NotNull Map<String, Object> map) {
map.forEach((key, value) -> System.out.printf(
"%s = %s (%s)%n",
key,
value, value.getClass().getSimpleName()
));
}
}
class Person {
private final String name;
private final int age;
private final double money;
public Person(String name) {
this.name = name;
age = 20;
money = 123.45;
}
public String getName() { return name; }
public int getAge() { return age; }
public double getMoney() { return money; }
}
回答:
所以序列化两次的意义是什么?
什么时候需要连续序列化两次呢?
应该直接可以把IO中的字节码序列化成对象
回答:
包上一层就好了
以上是 json 协议有规定连续两次序列化一个对象应该怎么样吗? 的全部内容, 来源链接: utcz.com/p/939084.html