You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C#将JSON1转换为符合特定规则的JSON2?

C# JSON转换:修正代码实现指定转换规则

转换规则

  • 若键对应的值为数组,仅保留索引0的元素;
  • 若TYPE数组位于DEVICE嵌套节点内,需删除TYPE数组值中除第0个元素对应的键值对之外的所有相关键值对。

输入JSON(JSON1)

{
  "VERSION": "VERSION 2.3.0",
  "COMPONENT": {
    "0": {
      "SUBID": 1,
      "TYPE": "TYPE 1",
      "OUTPUT TYPE": [
        "OUTPUT1",
        "OUTPUT2",
        "OUTPUT3"
      ],
      "UNIT": [
        "UNIT1",
        "UNIT2",
        "UNIT3"
      ],
      "DEVICE": {
        "SUBID": 2,
        "TYPE": [
          "DEVICE TYPE 1",
          "DEVICE TYPE 2",
          "DEVICE TYPE 3"
        ],
        "DEVICE TYPE 1": {
          "SUBID": 3,
          "TYPE": [
            "TYPE A",
            "TYPE B",
            "TYPE C",
            "TYPE D"
          ],
          "COLD": [
            "TRUE",
            "FALSE"
          ],
          "EXTERNAL": [
            "ON",
            "OFF"
          ]
        },
        "DEVICE TYPE 2": {
          "SUBID": 4,
          "TYPE": [
            "TYPE X",
            "TYPE Y",
            "TYPE Z"
          ],
          "VALUE": 0.0,
          "CO-EFFS": 0.0
        },
        "DEVICE TYPE 3": {
          "SUBID": 5,
          "EXTRACTION": [
            "1",
            "2"
          ],
          "EXTRACTION VALUE": 1.0,
          "APPROXIMATION": [
            "OFF",
            "ON"
          ]
        }
      },
      "CALIBRATION OFFSET AND GAIN": [
        "DISABLE",
        "ENABLE"
      ]
    }
  }
}

预期输出JSON(JSON2)

{
  "VERSION": "VERSION 2.3.0",
  "COMPONENT": {
    "0": {
      "SUBID": 1,
      "TYPE": "TYPE 1",
      "OUTPUT TYPE": "OUTPUT1",
      "UNIT": "UNIT1",
      "DEVICE": {
        "SUBID": 2,
        "TYPE": "DEVICE TYPE 1",
        "DEVICE TYPE 1": {
          "SUBID": 3,
          "TYPE": "TYPE A",
          "COLD": "TRUE",
          "EXTERNAL": "ON"
        }
      },
      "CALIBRATION OFFSET AND GAIN": "DISABLE"
    }
  }
}

当前输出JSON

{
  "VERSION": "VERSION 2.3.0",
  "COMPONENT": {
    "0": {
      "SUBID": 1,
      "TYPE": "TYPE 1",
      "OUTPUT TYPE": "OUTPUT1",
      "UNIT": "UNIT1",
      "DEVICE": {
        "SUBID": 2,
        "TYPE": "DEVICE TYPE 1",
        "DEVICE TYPE 1": {
          "SUBID": 3,
          "TYPE": "TYPE A",
          "COLD": "TRUE",
          "EXTERNAL": "ON"
        },
        "DEVICE TYPE 2": {
          "SUBID": 4,
          "TYPE": "TYPE X",
          "VALUE": 0.0,
          "CO-EFFS": 0.0
        },
        "DEVICE TYPE 3": {
          "SUBID": 5,
          "EXTRACTION": "1",
          "EXTRACTION VALUE": 1.0,
          "APPROXIMATION": "OFF"
        }
      },
      "CALIBRATION OFFSET AND GAIN": "DISABLE"
    }
  }
}

当前尝试的代码

public static void Main(String[] args)
{
     // change the file path 
    //var root = JObject.Parse(File.ReadAllText("C:/Users/path_to_input_json/input.json"));
    var root = JObject.Parse(@"{ ""VERSION"":""VERSION 2.3.0"",""COMPONENT"":{ ""0"":{ ""SUBID"":1,""TYPE"":""TYPE 1"",""OUTPUT TYPE"":[""OUTPUT1"",""OUTPUT2"",""OUTPUT3""],""UNIT"":[""UNIT1"",""UNIT2"",""UNIT3""],""DEVICE"":{""SUBID"":2,""TYPE"":[""DEVICE TYPE 1"",""DEVICE TYPE 2"",""DEVICE TYPE 3""],""DEVICE TYPE 1"":{""SUBID"":3,""TYPE"":[""TYPE A"",""TYPE B"",""TYPE C"",""TYPE D""],""COLD"":[""TRUE"",""FALSE""],""EXTERNAL"":[""ON"",""OFF""]
},""DEVICE TYPE 2"":{""SUBID"":4,""TYPE"":[""TYPE X"",""TYPE Y"",""TYPE Z""],""VALUE"":0,""CO-EFFS"":0},""DEVICE TYPE 3"":{""SUBID"":5,""EXTRACTION"":[""1"",""2""],""EXTRACTION VALUE"":1,""APPROXIMATION"":[""OFF"",""ON""]}},""CALIBRATION OFFSET AND GAIN"":[""DISABLE"",""ENABLE""]}}}");
    var descendants = root.DescendantsAndSelf().ToList();
    List<string> sensor_subtype_list = new List<string>();
    foreach (var d in descendants)
    {
        var jProp = d as JProperty;
        if (jProp != null)
        {
            if (jProp?.Value is JArray array)
            {
                if (jProp.Name == "TYPE")
                {
                    var value = jProp.Value as JArray;
                    sensor_subtype_list = value.ToObject<List<string>>();
                    jProp.Value = jProp.Value[0];
                }
                else
                {
                    if (sensor_subtype_list.Count != 0)
                    {
                        if (sensor_subtype_list.Contains(jProp.Name) && jProp.Name != sensor_subtype_list[0])
                        {
                            jProp.Remove();
                        }
                        else
                        {
                            jProp.Value = jProp.Value[0];
                        }
                    }
                    else
                    {
                        jProp.Value = jProp.Value[0];
                    }
                }
            }
            else
            {
                if (sensor_subtype_list.Count != 0)
                {
                    if (sensor_subtype_list.Contains(jProp.Name) && jProp.Name != sensor_subtype_list[0])
                    {
                        jProp.Remove();
                    }
                }
            }
        }
    }
    Console.WriteLine(root.ToString());
}

问题分析与修正代码

原代码的问题在于使用全局的sensor_subtype_list,处理DEVICE节点内的TYPE数组后未及时清理上下文,导致无法准确删除DEVICE下多余的子节点,且遍历逻辑未覆盖嵌套节点的处理优先级。

修正后的代码采用递归方式处理每个节点,确保上下文独立,严格遵循转换规则:

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    public static void Main(String[] args)
    {
        var root = JObject.Parse(@"{ ""VERSION"":""VERSION 2.3.0"",""COMPONENT"":{ ""0"":{ ""SUBID"":1,""TYPE"":""TYPE 1"",""OUTPUT TYPE"":[""OUTPUT1"",""OUTPUT2"",""OUTPUT3""],""UNIT"":[""UNIT1"",""UNIT2"",""UNIT3""],""DEVICE"":{""SUBID"":2,""TYPE"":[""DEVICE TYPE 1"",""DEVICE TYPE 2"",""DEVICE TYPE 3""],""DEVICE TYPE 1"":{""SUBID"":3,""TYPE"":[""TYPE A"",""TYPE B"",""TYPE C"",""TYPE D""],""COLD"":[""TRUE"",""FALSE""],""EXTERNAL"":[""ON"",""OFF""]
    },""DEVICE TYPE 2"":{""SUBID"":4,""TYPE"":[""TYPE X"",""TYPE Y"",""TYPE Z""],""VALUE"":0,""CO-EFFS"":0},""DEVICE TYPE 3"":{""SUBID"":5,""EXTRACTION"":[""1"",""2""],""EXTRACTION VALUE"":1,""APPROXIMATION"":[""OFF"",""ON""]}},""CALIBRATION OFFSET AND GAIN"":[""DISABLE"",""ENABLE""]}}}");
        
        ProcessNode(root);
        Console.WriteLine(root.ToString());
    }

    private static void ProcessNode(JToken node)
    {
        if (node is JObject obj)
        {
            // 先递归处理所有子属性,保证嵌套结构先完成转换
            var properties = obj.Properties().ToList();
            foreach (var prop in properties)
            {
                ProcessNode(prop.Value);
            }

            // 处理当前节点的TYPE数组逻辑
            var typeProp = obj.Property("TYPE");
            if (typeProp != null && typeProp.Value is JArray typeArray)
            {
                // 将TYPE数组替换为第一个元素
                string keepTypeName = typeArray[0].ToString();
                typeProp.Value = keepTypeName;

                // 删除TYPE数组中除第一个元素外对应的所有属性
                var typesToRemove = typeArray.Skip(1).Select(t => t.ToString());
                foreach (var typeName in typesToRemove)
                {
                    obj.Property(typeName)?.Remove();
                }
            }
        }
        else if (node is JArray array)
        {
            // 数组仅保留第一个元素,若元素是复杂类型则继续递归处理
            if (array.Count > 0)
            {
                var firstElement = array[0].DeepClone();
                array.ReplaceAll(firstElement);
                ProcessNode(firstElement);
            }
        }
    }
}

修正说明

  1. 递归处理节点:确保所有嵌套层级的JSON结构都能被遍历和转换;
  2. 先子后父的处理顺序:先完成子节点的数组转换和清理,再处理当前节点的TYPE数组逻辑,避免上下文混乱;
  3. 精准删除冗余属性:针对TYPE数组所在的父节点,直接删除数组后续元素对应的属性,确保只保留指定节点;
  4. 数组转换逻辑:将所有数组替换为第一个元素,若元素是对象或数组则继续递归处理,保证嵌套数组也符合规则。

内容的提问来源于stack exchange,提问作者DeLorean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 09:15:11