将Json结构展平

news2024/11/15 15:58:08

前言

技术群里面一个哥们在群里提了一个问题,怎么把Json的树形结构展平成一层
在线Json格式化工具

将这个JSON

在这里插入图片描述

展平成这样

在这里插入图片描述

代码

使用方法

static void Main(string[] args)
{
    //将测试对象转换成测试Json
    var json = JsonConvert.SerializeObject(new
    {
        Id = 1,
        Name = "张三",
        Childs = new[]
        {
            new
            {
                Id = 2,
                Name = "李四"
            },
            new
            {
                Id = 3,
                Name = "王五"
            }
        },
        Dogs = new []
        {
            new
            {
                Id = 10,
                DogName = "来福"
            }
        }
    });
    //使用Newtonsoft.Json解析Json字符串获取Json结构对象
    var jObject = (JToken)JsonConvert.DeserializeObject(json);
    //调用展平Json函数得到展平后的对象列表
    var result = FlattenJsonUtil.Flatten(jObject, null);
    //将展平后的对象列表转换成Json字符串
    var rJson = FlattenJsonUtil.ToJson(result);
    //将展平后的Json字符串输出到控制台上
    Console.WriteLine(rJson);
}

展平Json帮助类

public class FlattenJsonUtil
{
    public class JsonKey
    {
        /// <summary>
        /// 键名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 父亲节点
        /// </summary>
        public JsonKey Parent { get; set; }

        /// <summary>
        /// 创建新Key
        /// </summary>
        public static JsonKey CreateKey(JsonKey parentKey, string name)
        {
            return new JsonKey
            {
                Parent = parentKey,
                Name = name
            };
        }

        public override string ToString()
        {
            var names = new List<string>();
            for (var i = this; i != null; i = i.Parent)
            {
                names.Add(i.Name);
            }

            names.Reverse();
            return string.Join("_", names);
        }
    }

    public class JsonNode
    {
        /// <summary>
        /// 键值
        /// </summary>
        public JsonKey Key { get; set; }

        /// <summary>
        /// 字符串、数字、null、日期
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// 前面的节点
        /// </summary>
        public JsonNode Previous { get; set; }

        /// <summary>
        /// 复制并设置前面对象
        /// </summary>
        public JsonNode CopyAndSetPrevious(JsonNode jsonNode)
        {
            List<JsonNode> nodes = new List<JsonNode>()
            {
                this
            };
            var top = this;
            while (top.Previous != null)
            {
                top = top.Previous;
                nodes.Add(top);
            }

            var last = jsonNode;
            //循环克隆一遍
            for (var i = nodes.Count - 1; i >= 0; i--)
            {
                var node = nodes[i];
                last = new JsonNode
                {
                    Key = node.Key,
                    Previous = last,
                    Value = node.Value
                };
            }

            return last;
        }

        public override string ToString()
        {
            var items = new List<string>();
            for (var i = this; i != null; i = i.Previous)
            {
                items.Add($"\"{i.Key}\":{i.Value}");
            }

            items.Reverse();
            return $"{{{string.Join(",", items)}}}";
        }
    }

    public static string ToJson(List<JsonNode> nodes)
    {
        return $"[{string.Join(",", nodes)}]";
    }

    /// <summary>
    /// 展平Json
    /// </summary>
    public static List<JsonNode> Flatten(JToken json, JsonKey parentKey)
    {
        //对象
        if (json.Type == JTokenType.Object)
        {
            List<JsonNode> result = new List<JsonNode>();
            foreach (var property in ((JObject)json).Properties())
            {
                var key = JsonKey.CreateKey(parentKey, property.Name);
                var value = Flatten(property.Value, key);
                result = MergeJsonNodes(result, value);
            }

            return result;
        }

        if (json.Type == JTokenType.Array)
        {
            List<JsonNode> result = new List<JsonNode>();
            foreach (var jToken in (JArray)json)
            {
                var value = Flatten(jToken, parentKey);
                result.AddRange(value);
            }

            return result;
        }

        return new List<JsonNode>
        {
            new JsonNode
            {
                Key = parentKey,
                Value = JsonValueToString(json)
            }
        };
    }

    private static string JsonValueToString(JToken json)
    {
        if (json.Type == JTokenType.String || json.Type == JTokenType.Date)
        {
            return $"\"{json}\"";
        }

        return json.ToString();
    }

    /// <summary>
    /// 合并结果集
    /// </summary>
    private static List<JsonNode> MergeJsonNodes(List<JsonNode> result, List<JsonNode> value)
    {
        if (result.Count == 0)
        {
            return value;
        }

        if (value.Count == 1)
        {
            var first = value.First();
            return result.Select(x => first.CopyAndSetPrevious(x)).ToList();
        }

        return result.SelectMany(r => value.Select(v => v.CopyAndSetPrevious(r))).ToList();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/731617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据分析 - 基础入门之NumPy⑤】NumPy基本操作 - 二

知识目录 前言一、聚合函数二、矩阵操作2.1 算术运算2.2 线性代数2.3 其他数学操作 三、广播机制3.1 广播的原则3.2 案例 四、排序五、文件操作结语相关导读 前言 大家好&#xff01;本期给大家带来的是【数据分析 - 基础入门之NumPy⑤】NumPy基本操作 - 二&#xff0c;收录于…

t113i不查网线启动,内核[ cut here ]崩溃问题解决

前言 环境介绍&#xff1a; 1.编译环境 Ubuntu 18.04.5 LTS 2.SDK T113-i_v1.0 3.单板 迅龙TLT113-EVM-A1.1-000 自制底板 # 一、现象 插上网线启动&#xff0c;内核打印信息正常 不插网线启动&#xff0c;内核存在CPU崩溃打印[ cut here ] 二、问题根因 根据错误…

超详细JDK下载与安装步骤

目录 一、创建软件文件夹 二、安装软件 三、配置环境变量 四、 测试环境变量 一、创建软件文件夹 c盘目录创建devloop/Java/jdk1.8文件夹和devloop/Java/jre1.8文件夹 二、安装软件 打开jdk安装包 选择下一步 三、配置环境变量 右击此电脑&#xff0c;点击属性 点击高级系…

leetcode 513. 找树左下角的值

2023.7.7 题意要求是最底层的节点&#xff0c;则用层序遍历是最合适的&#xff0c;每一层遍历将元素放入一个数组中&#xff0c;等到最后一层遍历完之后&#xff0c;取这个数组的第一个元素即为所求节点值。 下面上代码&#xff1a; class Solution { public:int findBottomLe…

OpenCV在一张图片上以不同的透明度添加另一张图片

// 包含必要的OpenCV头文件 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv;// 定义全局变量 #define WINDOW_NAME "线

ACL 2023|如何智能生成吸引人又符合实际的标题?

夕小瑶科技说 原创 作者 | 小戏、Python 标题生成&#xff0c;乍一看似乎并不是一个复杂的任务&#xff0c;要数据简单的爬虫就可以获得许多标题-文本对&#xff0c;要评价通过用户点击与浏览的次数就多少可以区分“好标题”与“坏标题”&#xff0c;万事俱备使用一些经典的监…

Tomcat安装与配置(详细教程)

一、安装Tomcat服务器 1.下载地址&#xff08;Tomcat官网&#xff09;http://tomcat.apache.org/ 2.将下载的zip文件解压到指定的目录&#xff08;例如&#xff1a;D盘&#xff0c;目录不要有中文&#xff09; D:\apache-tomcat-9.0.43 二、配置Tomcat环境变量 &#xff08;…

Scrap爬虫框架集成Selenium来解析动态网页

1、爬虫项目单独使用scrpay框架的不足 当前网站普遍采用了javascript 动态页面&#xff0c;特别是vue与react的普及&#xff0c;使用scrapy框架定位动态网页元素十分困难&#xff0c;而selenium是最流行的浏览器自动化工具&#xff0c;可以模拟浏览器来操作网页&#xff0c;解…

金融时间序列预测方法合集:CNN、LSTM、随机森林、ARMA预测股票价格(适用于时序问题)、相似度计算、各类评判指标绘图(数学建模科研适用)

项目设计集合&#xff08;人工智能方向&#xff09;&#xff1a;助力新人快速实战掌握技能、自主完成项目设计升级&#xff0c;提升自身的硬实力&#xff08;不仅限NLP、知识图谱、计算机视觉等领域&#xff09;&#xff1a;汇总有意义的项目设计集合&#xff0c;助力新人快速实…

Junit 快速入门

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录 为什么学 JunitJunit 相关技术注解TestDisabledBeforeAll, AfterAllBeforeEach, AfterEach 参数化单参数CSV 获取参数多参数方…

华为云书库《Spring Boot2系列实战教程》电子书

华为开发者大会PaaS生态电子书推荐&#xff0c;助你成为了不起的开发者&#xff01; 处理Spring Boot 常见企业级需求&#xff0c;《Spring Boot2系列实战教程》来了&#xff01; 点击下方进入华为云官网 https://auth.huaweicloud.com/authui/login.html?localezh-cn&…

MySQL基础知识(一)-超详细Windows系统安装MySQL详细教程

1.简介 原计划&#xff0c;今天这篇想要给小伙伴们讲解一下python操作mysql数据库&#xff0c;但是由于近期换了一台新的电脑&#xff0c;所以一看mysql数据库都没安装&#xff0c;所有才有了这篇文章。尽管网上不乏此类型的文章&#xff0c;但是刚好自己要安装&#xff0c;所以…

C语言 base32与base64加解密

概述 Base32、Base64编码就是分别用32个、64个可打印字符表示二进制数据。 一、Base32规则 32 2^5&#xff0c;所以需要5 Bit来表示一个base32字符。一个字节8 Bit&#xff0c;5和8的最小公倍数是40。编码的过程中&#xff0c;以5个字节为一组转为8个base32字符&#xff0c;不…

python OA流程图xml文件画图 graphviz的使用

下面的公文发文的流程图&#xff0c;虽然流程环节有坐标信息&#xff0c;但graphviz设置pos参数效果也不是太好 问题在于如何为流程环节设置绝对坐标 D:\Study\myproject\Python_auto_office\flow_report\utils\draw_image.py 通过xml流程文件绘制流程图 import graphviz …

[期末网页作业]-小米官网(html+css+js)

今天&#xff0c;我非常高兴地向大家展示我的最新成果——仿写小米官网的页面。经过一个漫长的期末考试季节&#xff0c;我终于完成了这个耗费了许多心血的项目。在这个过程中&#xff0c;我付出了大量的时间和努力来确保每一个细节都尽善尽美。 首先&#xff0c;我注重了页面的…

【BMS】电池能量管理:充电管理(含关键参数)

&#x1f50b; 电池包能量管理&#xff1a;充电管理&#xff08;含关键参数&#xff09; &#x1f50b; 零、友情提示&#xff1a;若时间有限或者有基础的同学可直接跳至第四章查看一、以通信为基础1.典型电路2.软件时序 二、充电过程&#xff08;常规&#xff09;️1.充电参数…

【剑指offer】6.二叉树的下一个结点(java)

文章目录 二叉树的下一个结点描述输入描述&#xff1a;返回值描述&#xff1a;示例1示例2示例3示例4思路完整代码 二叉树的下一个结点 描述 给定一个二叉树其中的一个结点&#xff0c;请找出中序遍历顺序的下一个结点并且返回。注意&#xff0c;树中的结点不仅包含左右子结点…

JAVA leetCode 13. 罗马数字转整数

方法一&#xff1a;1.通过hashmap来保存字符与数字之间的关系 2&#xff1a;根据罗马数字转整数的特点&#xff0c;当前字符比右边的字符小并且不是最后一个字符就说明在计算总数时该字符的符号是负&#xff0c;反之即为正 代码展示&#xff1a; public static int romanToIn…

Spring Boot中的Hibernate是什么,如何使用

Spring Boot中的Hibernate是什么&#xff0c;如何使用 Hibernate是一个流行的Java ORM框架&#xff0c;它提供了一种将Java对象映射到关系数据库表的方法。Spring Boot集成了Hibernate&#xff0c;使得在开发Web应用程序时可以轻松地使用Hibernate操作数据库。本文将介绍Sprin…

记一次阿里云被挖矿处理记录

摘要 莫名其妙的服务器就被攻击了&#xff0c;又被薅了羊毛&#xff0c;当做免费的挖矿劳动力了。 一、起因 上班&#xff08;摸鱼&#xff09;好好的&#xff0c;突然收到一条阿里云的推送短信&#xff0c;不看不知道&#xff0c;两台服务器被拉去作为苦力&#xff0c;挖矿去…