做一次面向对象的体操:将JSON字符串转换为嵌套对象的一种方法

237 篇文章 4 订阅
237 篇文章 1 订阅

能不能把这个JSON串转成相应的对象,更易于使用呢? 为了方便讲解,这里重复写下JSON串。

{
“item:s_id:18006666”: “1024”,
“item:s_id:18008888”: “1024”,
“item:g_id:18006666”: “6666”,
“item:g_id:18008888”: “8888”,
“item:num:18008888”: “8”,
“item:num:18006666”: “6”,
“item:item_core_id:18006666”: “9876666”,
“item:item_core_id:18008888”: “9878888”,
“item:order_no:18006666”: “E20171013174712025”,
“item:order_no:18008888”: “E20171013174712025”,
“item:id:18008888”: “18008888”,
“item:id:18006666”: “18006666”,

“item_core:num:9878888”: “8”,
“item_core:num:9876666”: “6”,
“item_core:id:9876666”: “9876666”,
“item_core:id:9878888”: “9878888”,

“item_price:item_id:1000”: “9876666”,
“item_price:item_id:2000”: “9878888”,
“item_price:price:1000”: “100”,
“item_price:price:2000”: “200”,
“item_price:id:2000”: “2000”,
“item_price:id:1000”: “1000”,

“item_price_change_log:id:1111”: “1111”,
“item_price_change_log:id:2222”: “2222”,
“item_price_change_log:item_id:1111”: “9876666”,
“item_price_change_log:item_id:2222”: “9878888”,
“item_price_change_log:detail:1111”: “haha1111”,
“item_price_change_log:detail:2222”: “haha2222”,
“item_price_change_log:id:3333”: “3333”,
“item_price_change_log:id:4444”: “4444”,
“item_price_change_log:item_id:3333”: “9876666”,
“item_price_change_log:item_id:4444”: “9878888”,
“item_price_change_log:detail:3333”: “haha3333”,
“item_price_change_log:detail:4444”: “haha4444”
}
思路与实现
要解决这个问题,需要有一个清晰的思路。

首先,需要知道应该转成怎样的目标对象。
其次,需要找到一种方法,建立从JSON串到目标对象的桥梁。
推断目标对象
仔细观察可知,每个 key 都是 tablename:field:id 组成,其中 table:id 相同的可以构成一个对象的数据; 此外,不同的tablename 对应不同的对象,而这些对象之间可以通过相同的 itemId 关联。

根据对JSON字符串的仔细分析(尤其是字段的关联性),可以知道: 目标对象应该类似如下嵌套对象:

@Getter
@Setter
public class ItemCore {
private String id;
private String num;

private Item item;

private ItemPrice itemPrice;

private List itemPriceChangeLogs;

}

@Getter
@Setter
public class Item {
private String sId;
private String gId;
private String num;
private String orderNo;
private String id;
private String itemCoreId;

}

@Getter
@Setter
public class ItemPrice {
private String itemId;
private String price;
private String id;
}

@Getter
@Setter
public class ItemPriceChangeLog {
private String id;
private String itemId;
private String detail;
}
注意到,对象里的属性是驼峰式,JSON串里的字段是下划线,遵循各自领域内的命名惯例。这里需要用到一个函数,将Map的key从下划线转成驼峰。这个方法在 《Java实现递归将嵌套Map里的字段名由驼峰转为下划线》 给出。

明确了目标对象,就成功了 30%。 接下来,需要找到一种方法,从指定字符串转换到这个对象。

算法设计
由于 JSON 并不是与对象结构对应的嵌套结构。需要先转成容易处理的Map对象。这里的一种思路是,

STEP1: 将 table:id 相同的字段及值分组聚合,得到 Map[tablename:id, mapForKey[field, value]];

STEP2: 将每个 mapForKey[field, value] 转成 tablename 对应的单个对象 Item, ItemCore, ItemPrice, ItemPriceChangeLog;

STEP3: 然后根据 itemId 来关联这些对象,组成最终对象。

代码实现
package zzz.study.algorithm.object;

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import zzz.study.datastructure.map.TransferUtil;
import static zzz.study.utils.BeanUtil.map2Bean;

public class MapToObject {

private static final String json = “{

+ ” “item:s_id:18006666”: “1024”,

+ ” “item:s_id:18008888”: “1024”,

+ ” “item:g_id:18006666”: “6666”,

+ ” “item:g_id:18008888”: “8888”,

+ ” “item:num:18008888”: “8”,

+ ” “item:num:18006666”: “6”,

+ ” “item:item_core_id:18006666”: “9876666”,

+ ” “item:item_core_id:18008888”: “9878888”,

+ ” “item:order_no:18006666”: “E20171013174712025”,

+ ” “item:order_no:18008888”: “E20171013174712025”,

+ ” “item:id:18008888”: “18008888”,

+ ” “item:id:18006666”: “18006666”,

+ ”

+ ” “item_core:num:9878888”: “8”,

+ ” “item_core:num:9876666”: “6”,

+ ” “item_core:id:9876666”: “9876666”,

+ ” “item_core:id:9878888”: “9878888”,

+ ”

+ ” “item_price:item_id:1000”: “9876666”,

+ ” “item_price:item_id:2000”: “9878888”,

+ ” “item_price:price:1000”: “100”,

+ ” “item_price:price:2000”: “200”,

+ ” “item_price:id:2000”: “2000”,

+ ” “item_price:id:1000”: “1000”,

+ ”

+ ” “item_price_change_log:id:1111”: “1111”,

+ ” “item_price_change_log:id:2222”: “2222”,

+ ” “item_price_change_log:item_id:1111”: “9876666”,

+ ” “item_price_change_log:item_id:2222”: “9878888”,

+ ” “item_price_change_log:detail:1111”: “haha1111”,

+ ” “item_price_change_log:detail:2222”: “haha2222”,

+ ” “item_price_change_log:id:3333”: “3333”,

+ ” “item_price_change_log:id:4444”: “4444”,

+ ” “item_price_change_log:item_id:3333”: “9876666”,

+ ” “item_price_change_log:item_id:4444”: “9878888”,

+ ” “item_price_change_log:detail:3333”: “haha3333”,

+ ” “item_price_change_log:detail:4444”: “haha4444”

+ “}”;

public static void main(String[] args) {
Order order = transferOrder(json);
System.out.println(JSON.toJSONString(order));
}

public static Order transferOrder(String json) {
return relate(underline2camelForMap(group(json)));
}

/**
* 转换成 Map[tablename:id => Map[“field”: value]]
*/
public static Map

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值