|
|
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;
|
|
|
}
|
|
|
}
|
|
|
}
|