www.91084.com

GVKun编程网logo

使用Java和Jackson将Json序列化为通用结构而无需模式(java json 序列化)

15

本文将为您提供关于使用Java和Jackson将Json序列化为通用结构而无需模式的详细介绍,我们还将为您解释javajson序列化的相关知识,同时,我们还将为您提供关于android–只使用Jack

本文将为您提供关于使用Java和Jackson将Json序列化为通用结构而无需模式的详细介绍,我们还将为您解释java json 序列化的相关知识,同时,我们还将为您提供关于android – 只使用Jackson将超类字段序列化为JSON、angularjs – 让Jackson将Java 8 Instant序列化为纪元毫秒的有效方法吗?、Fastjson和Jackson序列化和读取json的性能实测、Jackson真的无法将json反序列化为通用类型吗?的实用信息。

本文目录一览:

使用Java和Jackson将Json序列化为通用结构而无需模式(java json 序列化)

使用Java和Jackson将Json序列化为通用结构而无需模式(java json 序列化)

我需要序列化JSON,而不必附加到生成对象的特定架构,例如,某些通用set / map / hashmap。

作为输入 ,我有一个带有JSON的字符串。我不知道该JSON的架构。

作为输出, 我想要一个具有输入键值序列化的Java对象(例如Hashmap或类似对象)。

请注意, 输入JSON既具有基本字段,又具有Array / List。

我必须使用Java和Jackson(或其他一些库)。我怎么可能那样做?

答案1

小编典典

Jackson数据绑定功能可以使用String键和Object值(也可以是地图或集合)将任何json输入读取到Map中。您只是告诉映射器,您想将json读入映射。您可以通过给映射器适当的类型引用来做到这一点:

import java.util.*;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.ObjectMapper;public class Test{    public static void main(String[] args)    {        try {            String json = "{ "                    + "\"string-property\": \"string-value\", "                    + "\"int-property\": 1, "                    + "\"bool-property\": true, "                    + "\"collection-property\": [\"a\", \"b\", \"c\"], "                    + "\"map-property\": {\"inner-property\": \"inner-value\"} "                    + "}";            ObjectMapper mapper = new ObjectMapper();            Map<String, Object> map = new HashMap<>();            // convert JSON string to Map            map = mapper.readValue(json, new TypeReference<Map<String, Object>>(){});            System.out.println("input: " + json);            System.out.println("output:");            for (Map.Entry<String, Object> entry : map.entrySet()) {                System.out.println("key: " + entry.getKey());                System.out.println("value type: " + entry.getValue().getClass());                System.out.println("value: " + entry.getValue().toString());            }        } catch (Exception e) {            e.printStackTrace();        }    }}

输出:

input: { "string-property": "string-value", "int-property": 1, "bool-property": true, "collection-property": ["a", "b", "c"], "map-property": {"inner-property": "inner-value"} }output:key: string-propertyvalue type: class java.lang.Stringvalue: string-valuekey: int-propertyvalue type: class java.lang.Integervalue: 1key: bool-propertyvalue type: class java.lang.Booleanvalue: truekey: collection-propertyvalue type: class java.util.ArrayListvalue: [a, b, c]key: map-propertyvalue type: class java.util.LinkedHashMapvalue: {inner-property=inner-value}

android – 只使用Jackson将超类字段序列化为JSON

android – 只使用Jackson将超类字段序列化为JSON

我正在与杰克逊序列化一个班级的实例.
仅序列化此实例的超类的字段的最佳方法是什么?

目前我必须将JSONIgnore注释添加到我的子类中的每个方法,
有没有更好的方法呢?

解决方法

假设您可以通过ObjectMapper直接控制序列化过程,您可以通过创建特定于您的超类的 ObjectWriter来轻松实现此目的.以下是一些示例代码.

public class Account implements Serializable {
    private String accountNumber;
    private String routingNumber;
    private BigDecimal balance;

    // Constructors,setters/getters
}

public class SavingsAccount extends Account {
    private BigDecimal savingsRate;

    // Constructors,setters/getters
}


final ObjectMapper mapper = new ObjectMapper();
final ObjectWriter writer = mapper.writerWithType(Account.class);
final ByteArrayOutputStream baos = new ByteArrayOutputStream(6400);
final SavingsAccount account = new SavingsAccount("0031-3402-2189","0009835011203",BigDecimal.valueOf(53500),BigDecimal.valueOf(0.3));

writer.writeValue(baos,account);
final String results = new String(baos.toByteArray());
baos.close();

System.out.println(results);

运行上面的代码说明了Jackson编写超类字段,即使运行时实例属于子类类型.

{"accountNumber":"0031-3402-2189","routingNumber":"0009835011203","balance":53500}

编辑:

Thanks,but in my case I try to achieve this behavIoUr for several
classes are fields of the outer class that I serialize. Can I define
the types more in general?

这种情况更容易处理.只需使用@JsonSerialize注释外部类中的相应字段.如果将字段声明为超类类型,则将键入设置为静态.这将使用编译时类型而不是运行时类型将那些字段标记为Jackson以进行序列化.

另一方面,如果将字段声明为子类类型,则将using设置为超类.

以下示例使用我在上面进一步定义的类:

public class BankCustomer implements Serializable {
    @JsonSerialize(typing=Typing.STATIC)
    private Account cdAccount;

    @JsonSerialize(using=Account.class)
    private SavingsAccount savingsAccount;
}

angularjs – 让Jackson将Java 8 Instant序列化为纪元毫秒的有效方法吗?

angularjs – 让Jackson将Java 8 Instant序列化为纪元毫秒的有效方法吗?

使用带有Jackson JSON解析后端的Spring RestControllers,前端使用AngularJS.我正在寻找一种有效的方法让Jackson序列化一个Instant作为纪元毫秒,以便随后使用 JavaScript代码. (在浏览器方面,我希望通过Angular的 Date Filter提供epoch ms:{{myInstantVal | date:’short’}}以获得我想要的日期格式.)

在Java方面,杰克逊将使用的吸气剂就是:

public Instant getMyInstantVal() { return myInstantVal; }

序列化不会按原样运行,因为默认情况下,jackson-datatype-jsr310不会返回Epoch毫秒数.我看着将@JsonFormat添加到上面的getter中以将Instant变成前端可以使用的东西,但是它遇到两个问题:(1)我可以提供它的模式显然仅限于SimpleDateFormat,它不提供“ epoch milliseconds“选项,以及(2)当我尝试将Instant作为格式化日期发送到浏览器时,Jackson会抛出异常,因为@JsonFormat注释需要Instants的TimeZone属性,我不想硬编码为它会因用户而异.

到目前为止我的解决方案(并且工作正常)是使用@JsonGetter创建替换getter,这会导致Jackson使用此方法来序列化myInstantVal:

@JsonGetter("myInstantVal")
public long getMyInstantValEpoch() {
    return myInstantVal.toEpochMilli();
}

这是正确的方法吗?或者是否有一个很好的注释,我错过了我可以放在getMyInstantVal()所以我不必创建这些额外的方法?

解决方法

您只需阅读链接到的README.我的重点:

Most JSR-310 types are serialized as numbers (integers or decimals as appropriate) if the SerializationFeature#WRITE_DATES_AS_TIMESTAMPS feature is enabled,and otherwise are serialized in standard ISO-8601 string representation.

[…]

Granularity of timestamps is controlled through the companion features SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS and DeserializationFeature#READ_DATE_TIMESTAMPS_AS_NANOSECONDS. For serialization,timestamps are written as fractional numbers (decimals),where the number is seconds and the decimal is fractional seconds,if WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS is enabled (it is by default),with resolution as fine as nanoseconds depending on the underlying JDK implementation. If WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS is disabled,timestamps are written as a whole number of milliseconds.

Fastjson和Jackson序列化和读取json的性能实测

Fastjson和Jackson序列化和读取json的性能实测

偶然间看到的阿里出品的Fastjson,网上对这个json包好评如潮,性能胜Jackson10倍。
本人本着眼见为实的想法,自己测试一下两者的性能比较。

###测试### POJO对象名字为User,具体代码就不贴了,里面有两个属性,分别是int类型的id和String类型的name,很简单的一个类。

测试程序(只是简单的测试下,这里并未深究其中的各种构造方法)

    public class MyMain {
	private static final int TEST_CASE_NUM = 1000;
	public static void main(String args[]) throws IOException {

		List<User> users = new ArrayList<User>();
		Random random = new Random();

		for (int i = 0; i < TEST_CASE_NUM; i++) {
			User user = new User();
			user.setId(random.nextInt(10));
			user.setName("123");
			users.add(user);
		}

		Monitor.begin();
		for (User u : users){
			String s = JSON.toJSONString(u);
		}
		Monitor.end("serilization of fastjson");

		Monitor.begin();
                                    /**
		 * 这里仅创建一个ObjectMapper实例
		 * 而网上的很多测试程序中,把实例的创建过程
		 * 加入到了for循环中,因此测出来的序列化性能
		 * 有10倍之差,其实其中大部分都消耗在了ObejectMapper
		 * 实例创建上。
		 */
		ObjectMapper objectMapper = new ObjectMapper();
		for (User u : users){
			String s = objectMapper.writeValueAsString(u);
		}
		long endjackson = System.currentTimeMillis();
		Monitor.end("serilization of jackson");


		List<String> strs = new ArrayList<String>();
		for (int j = 0; j < TEST_CASE_NUM; j++) {
			String s = new String("{\"id\":1,\"name\":\"123\"}");
			strs.add(s);
		}

		Monitor.begin();
		for (String s : strs){
			User user = JSON.parseObject(s,User.class);
		}
		Monitor.end("reading string by fastjson");

		Monitor.begin();
                                    ObjectMapper obj = new ObjectMapper();
		for (String s : strs){
			User user = obj .readValue(s,User.class);
		}
		Monitor.end("reading string by jackson");
	}
}

运行程序得到输出:

    serilization of fastjson use 158 ms
serilization of jackson use 339 ms
reading string by fastjson use 49 ms
reading string by jackson use 73 ms

多次运行后结果相差甚微,比例关系基本保持稳定。由此可见fastjson并未如网上传言那般,性能较之于jackson提升10倍。如果将ObjectMapper实例的创建过程也从计时器中提取出来,哪么Jackson与fastjson的序列化性能几乎相同。
然而在反序列方面,fastjson以巨大的优势领先Jackson,将测试的用例个数增加至1000000,得到的输出为:

    reading string by fastjson use 505 ms
reading string by jackson use 1051 ms

fastjson几乎只需要Jackson的一半时间,这个表现相当亮眼。

在这里我们反序列化的字符串是按照实体类中属性的顺序排列的,如果打乱一下顺序呢?
这里还是使用1000000个测试用例,得到的输出结果为:

    reading string by fastjson use 715 ms
reading string by jackson use 1049 ms

因为fastjson默认开启了sort field martch优化算法,打乱顺序之后性能下降,但仍然领先Jackson不少。

###总结### 这次测试使用的是1.9.31版本的Jackson和1.1.39版本的fasijson,测试结果表名fastjson和Jackson在序列化性能上相差不大(主要ObjectMapper类新建实例耗费不少时间),但是在反序列化方面,fastjson要明显领先于Jackson。

Jackson真的无法将json反序列化为通用类型吗?

Jackson真的无法将json反序列化为通用类型吗?

我希望这个问题最终能找到一个答案,使之永远清楚。

有模特儿:

public class AgentResponse<T> {

    private T result;

    public AgentResponse(T result) {
        this.result = result;
    }
    public T getResult() {
        return result;
    }
}

JSON输入:

{"result":{"first-client-id":3,"test-mail-module":3,"third-client-id":3,"second-client-id":3}}

以及两种反序列化泛型类型的推荐方法:

mapper.readValue(out,new TypeReference<AgentResponse<Map<String,Integer>>>() {});

要么

JavaType javaType = mapper.getTypeFactory().constructParametricType(AgentResponse.class,Map.class);
mapper.readValue(out,javaType);

Jackson永远无法处理通用类型T,它认为这是JavaType的Map,但由于类型擦除而找到了对象类型构造函数参数,并抛出错误。那是杰克逊的臭虫,还是我做错了什么?TypeReference或JavaType的显式规范还有什么用?

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type,class com.fg.mail.smtp.AgentResponse<java.util.Map<java.lang.String,java.lang.Integer>>]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: java.io.InputStreamReader@4f2d26d; line: 1,column: 2]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:984)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2064)

关于使用Java和Jackson将Json序列化为通用结构而无需模式java json 序列化的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于android – 只使用Jackson将超类字段序列化为JSON、angularjs – 让Jackson将Java 8 Instant序列化为纪元毫秒的有效方法吗?、Fastjson和Jackson序列化和读取json的性能实测、Jackson真的无法将json反序列化为通用类型吗?等相关内容,可以在本站寻找。

本文标签: