You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
haoliang-net/Core/DataParser.cs

99 lines
4.0 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using CncModels.Entity;
using System.Linq;
using log4net;
namespace CncCollector.Core
{
/// <summary>
/// JSON 解析引擎:将原始 JSON 与品牌字段映射表结合,输出结构化字段字典。
/// </summary>
public static class DataParser
{
/// <summary>解析结果中的字段</summary>
public class ParsedField
{
/// <summary>字段名(标准化后)</summary>
public string FieldName { get; set; }
/// <summary>字段值</summary>
public object Value { get; set; }
/// <summary>数据类型</summary>
public string DataType { get; set; }
}
private static readonly ILog Log = LogManager.GetLogger(typeof(DataParser));
/// <summary>
/// 解析原始 JSON并根据品牌映射提取字段。
/// 该实现尽量适配常见结构JSON 为数组,元素包含一个 tags 数组tags 中的元素拥有 id/value。
/// </summary>
/// <param name="brandName">品牌名称,用于定位字段映射(若为 null尝试使用空映射</param>
/// <param name="json">原始 JSON 字符串</param>
/// <param name="brand">可选的品牌对象,包含映射信息</param>
/// <returns>解析后的字段字典Key 为标准字段名</returns>
public static Dictionary<string, ParsedField> Parse(string brandName, string json, Brand brand = null)
{
var result = new Dictionary<string, ParsedField>();
if (string.IsNullOrWhiteSpace(json)) return result;
try
{
var root = JArray.Parse(json);
// 优先使用传入的 brand若品牌包含字段映射来定位 tags
var mappings = brand?.BrandFieldMappings?.ToList() ?? new List<BrandFieldMapping>();
foreach (var item in root)
{
// 定位 tags 列表,默认字段路径为 "tags"
var tagsPath = brand?.TagsPath ?? "tags";
var tagsToken = item.SelectToken(tagsPath);
if (tagsToken == null) continue;
if (tagsToken is JArray tags)
{
foreach (var map in mappings)
{
var tag = tags.FirstOrDefault(t => string.Equals(t["id"]?.ToString(), map.FieldName, StringComparison.OrdinalIgnoreCase));
if (tag != null)
{
var raw = tag["value"]?.ToString();
var value = ConvertValue(raw, map.DataType);
var field = new ParsedField
{
FieldName = map.StandardField,
Value = value,
DataType = map.DataType
};
result[field.FieldName] = field;
}
}
}
// 解析到一个设备后就返回,简化实现
break;
}
}
catch (Exception ex)
{
Log.Error("DataParser 解析异常", ex);
}
return result;
}
private static object ConvertValue(string raw, string dataType)
{
if (string.IsNullOrWhiteSpace(raw)) return null;
if (string.Equals(dataType, "number", StringComparison.OrdinalIgnoreCase))
{
if (decimal.TryParse(raw, out var d)) return d;
}
// 去除形如 1219.00000 的尾缀
if (raw.EndsWith(".00000") && decimal.TryParse(raw.Replace(".00000", ""), out var d2))
{
return d2;
}
return raw;
}
}
}