最新消息:天气越来越冷,记得加一件厚衣裳

JSON Field下划线与驼峰格式转换

Java w3sun 2139浏览 0评论

背景

任何一门编程语言都有自己特有的编程规范,例如Java中标识符定义只能由字母、数字、下划线_、美元符号$组成不能含有其他符号,同时不能以数字开头、不能使用Java关键字、严格区分大小写并遵循驼峰命名方式。除了基本规范外,每个公司可能还有自己的内部其他规范,比如Java Bean转换成JSON时,如果JSON Field名称超过两个单词那么各单词需要小写并以下划线分割。本文将介绍几种将Java Bean序列化成JSON String时下划线与驼峰互相转换的方式。在开始之前先普及下JSON的标准定义:

JSON简介

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于开发人员阅读和编写,同时也易于机器解析和生成。 它是基于JavaScript Programming Language,Standard ECMA-262 3rd Edition – December 1999的一个子集,JSON采用完全独立于程序语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#,Java,JavaScript,Perl,Python等)。 这些特性使得JSON成为理想的数据交换语言,JSON建构于两种结构:

  • “名称/值”对的集合(A collection of name/value pairs):不同的编程语言中它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list)或者关联数组 (associative array);
  • 值的有序列表(An ordered list of values):在大部分语言中它被实现为数组(array),矢量(vector),列表(list),序列(sequence);

这些是通用的数据结构,几乎所有现代编程语言都以某种形式支持它们,这使得在各种编程语言之间交换同样格式的数据成为可能。 JSON具有以下这些形式:

对象(object) 是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,以“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

数组(array) 是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束,值之间使用“,”(逗号)分隔。

值(value) 可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array),这些结构可以嵌套。

字符串(string) 是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义,一个字符(character)即一个单独的字符串(character string)。JSON的字符串(string)与C或者Java的字符串非常相似。

数值(number)也与C或者Java的数值非常相似。只是JSON的数值没有使用八进制与十六进制格式。

同时,可以在任意标记之间添加空白,不影响数据的解析和生成。

测试用例

package com.w3sun.bean;

/**
 * @author: w3sun
 * @date: 2019/5/9 11:02
 * @description:
 */
public class Website {
    public String siteName;
    public String siteUrl;
    public String metaName;
    public Long articleCount;

    public Website() {
    }

    public Website(String siteName, String siteUrl, String metaName, Long articleCount) {
        this.siteName = siteName;
        this.siteUrl = siteUrl;
        this.metaName = metaName;
        this.articleCount = articleCount;
    }

    public String getSiteName() {
        return siteName;
    }

    public void setSiteName(String siteName) {
        this.siteName = siteName;
    }

    public String getSiteUrl() {
        return siteUrl;
    }

    public void setSiteUrl(String siteUrl) {
        this.siteUrl = siteUrl;
    }

    public String getMetaName() {
        return metaName;
    }

    public void setMetaName(String metaName) {
        this.metaName = metaName;
    }

    public Long getArticleCount() {
        return articleCount;
    }

    public void setArticleCount(Long articleCount) {
        this.articleCount = articleCount;
    }
}

测试数据

Website website = new Website();
website.setSiteName("Spark官网");
website.setSiteUrl("https://spark.apache.org");
website.setArticleCount(132L);
website.setMetaName("keywords");

下划线与驼峰格式转换

Java、C++、C#、Python等不同的编程语言都有相对应的JSON工具类,本文将基于Java通过常见的Gson、Fastjson、Jackson框架实现下划线与驼峰格式之间的格式转换;

通过Gson实现

Gson是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串。本文使用到Gson的GAV信息如下:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.0</version>
</dependency>

序列化

/**
 * 通过Gson将实例序列化为JSON String
 *
 * @param website Website对象
 */
private static String serializeByGson(Website website) {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
    Gson gson = gsonBuilder.create();
    return gson.toJson(website);
}

序列化为JSON String结果:

反序列化

/**
 * 通过Gson将JSON String反序列化为Website实例
 *
 * @param jsonString
 */
 private static Website deserializeByGson(String jsonString) {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
    Gson gson = gsonBuilder.create();
    return gson.fromJson(jsonString, Website.class);
}

JSON String反序列化为Website实例结果:

通过Gson实现下划线和驼峰格式之间转换时有一个注意事项,那就是反序列化时需要显式指定FieldNamingPolicy为LOWER_CASE_WITH_UNDERSCORES,否则会出现转换失败。

通过Fastjson实现

Fastjson是一个Java语言编写的高性能功能完善的JSON库,由阿里巴巴基于Apache 2.0协议开源。Fastjson采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。本文使用到的Fastjson GAV信息如下:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.58</version>
</dependency>

序列化

Fastjson将Website实例序列化成JSON String过程中,可以通过两种方式实现Field由驼峰到下划线格式的转换,一种是通过SerializeConfig,一种是在Website成员变量上添加JSONField注解。

通过SerializeConfig实现

/**
 * 通过Fastjson将实例序列化为JSON String
 *
 * @param website Website实例
 */
private static String serializeByFastjson(Website website) {
    SerializeConfig serializeConfig = new SerializeConfig();
    serializeConfig.setPropertyNamingStrategy(PropertyNamingStrategy.SnakeCase);
    return JSON.toJSONString(website, serializeConfig);
}

通过JSONField注解实现

相对于SerializeConfig方式,通过JSONField方式实现驼峰到下划线转换存在一定侵入性,而且如果字段过多手动设置也不是方便,暂不推荐该方式。

public class Website {
    @JSONField(name = "site_name")
    public String siteName;
    @JSONField(name = "site_url")
    public String siteUrl;
    @JSONField(name = "meta_name")
    public String metaName;
    @JSONField(name = "article_count")
    public Long articleCount;

    public Website() {
    }
    .......
}

如果采用JSONField注解方式直接通过SONObject.toJSONString(website)方式生成JSON String即可。上述两种序列化方式成JSON String的结果相同:

{"article_count":132,"meta_name":"keywords","site_name":"Spark官网","site_url":"https://spark.apache.org"}

反序列化

/**
 * 通过Fastjson将JSON String反序列化为Website实例
 *
 * @param jsonString
 */
private static Website deserializeByFastjson(String jsonString) {
    return JSON.parseObject(jsonString, Website.class);
}

反序列化生成实例时Fastjson可以自动实现对下划线和驼峰兼容:

通过Jackson实现

Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。本文使用到的Jackson GAV信息如下:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.9</version>
</dependency>

序列化

/**
 * 通过Jackson将实例序列化为JSON String
 *
 * @param website Website对象
 */
private static String serializeByJackson(Website website) throws JsonProcessingException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setPropertyNamingStrategy(com.fasterxml.jackson.databind.PropertyNamingStrategy.SNAKE_CASE);
    return objectMapper.writeValueAsString(website);
}

反序列化

与Gson将JSON String反序列化成Website实例时,需要显式指定FieldNamingPolicy为LOWER_CASE_WITH_UNDERSCORES,否则会出现转换失败。

/**
 * 通过Jackson将JSON String反序列化为Website实例
 *
 * @param jsonString
 */
private static Website deserializeByJackson(String jsonString) throws IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setPropertyNamingStrategy(com.fasterxml.jackson.databind.PropertyNamingStrategy.SNAKE_CASE);
    return objectMapper.readValue(jsonString, Website.class);
}

参考资料

https://www.json.org/json-zh.html

https://www.json.org/json-en.html

https://github.com/google/gson

https://github.com/alibaba/fastjson

http://fasterxml.com/

https://github.com/FasterXML/jackson

转载请注明:雪后西塘 » JSON Field下划线与驼峰格式转换

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址