Added deserialzor node for parsing the json to model ot list of model
Some checks failed
Build / build (push) Successful in 28s
CodeQL / Analyze (csharp) (push) Has been cancelled

This commit is contained in:
Ankitkumar Satapara
2026-04-25 00:37:53 +05:30
parent d4e6a7a06f
commit 77cd472f73
8 changed files with 450 additions and 1 deletions

View File

@@ -142,6 +142,191 @@ namespace Nodify.Calculator.Execution.Handlers
}
}
internal sealed class DeserializeHandler : INodeExecutionHandler
{
public bool CanHandle(OperationViewModel node, ExecutionContext ctx)
=> node is DeserializeOperationViewModel;
public void Execute(OperationViewModel node, ExecutionContext ctx)
{
var desVm = (DeserializeOperationViewModel)node;
var targetType = desVm.SelectedTargetType ?? "object";
// Read the Json input (first non-Triangle input)
var jsonInput = node.Input.FirstOrDefault(i => i.Shape != ConnectorShape.Triangle);
var raw = ctx.ReadInput(jsonInput) ?? "";
ctx.Log($"[DESERIALIZE] Input: {(raw.Length > 100 ? raw.Substring(0, 100) + "..." : raw)}");
ctx.Log($"[DESERIALIZE] Target type: {targetType}");
if (string.IsNullOrWhiteSpace(raw))
{
ctx.Log("[DESERIALIZE] ERROR: No JSON input provided.", logType.Error);
return;
}
// Ensure valid JSON
var trimmed = raw.Trim();
bool isJson = (trimmed.StartsWith("{") && trimmed.EndsWith("}"))
|| (trimmed.StartsWith("[") && trimmed.EndsWith("]"))
|| (trimmed.StartsWith("\"") && trimmed.EndsWith("\""));
if (!isJson)
{
try { raw = JsonConvert.SerializeObject(raw); }
catch { /* keep raw */ }
}
try
{
var token = JToken.Parse(raw);
if (targetType == "object")
{
var result = token.ToString(Formatting.None);
ctx.Outputs[node.NodeId] = result;
ctx.Log($"[DESERIALIZE] Output (object): {(result.Length > 100 ? result.Substring(0, 100) + "..." : result)}");
return;
}
if (targetType.StartsWith("List<") && targetType.EndsWith(">"))
{
var modelName = targetType.Substring(5, targetType.Length - 6);
var modelProps = LoadModelProperties(modelName, ctx);
var array = FindArray(token);
if (array == null)
{
ctx.Log($"[DESERIALIZE] ERROR: Could not find an array to convert to {targetType}.", logType.Error);
return;
}
if (modelProps != null && modelProps.Length > 0)
{
var projected = new JArray();
foreach (var item in array)
{
var proj = ProjectToModel(item, modelProps);
if (proj != null) projected.Add(proj);
}
var result = projected.ToString(Formatting.None);
ctx.Outputs[node.NodeId] = result;
ctx.Log($"[DESERIALIZE] Deserialized {projected.Count} items as {targetType}.");
}
else
{
var result = array.ToString(Formatting.None);
ctx.Outputs[node.NodeId] = result;
ctx.Log($"[DESERIALIZE] Model \"{modelName}\" not found, returning raw array ({array.Count} items).");
}
return;
}
// Single model
{
var modelProps = LoadModelProperties(targetType, ctx);
var obj = FindObject(token);
if (obj == null)
{
ctx.Log($"[DESERIALIZE] ERROR: Could not find an object to convert to {targetType}.", logType.Error);
return;
}
if (modelProps != null && modelProps.Length > 0)
{
var projected = ProjectToModel(obj, modelProps);
if (projected == null)
{
ctx.Log($"[DESERIALIZE] ERROR: Failed to project to {targetType}.", logType.Error);
return;
}
var result = projected.ToString(Formatting.None);
ctx.Outputs[node.NodeId] = result;
ctx.Log($"[DESERIALIZE] Deserialized as {targetType} with {projected.Count} properties.");
}
else
{
var result = obj.ToString(Formatting.None);
ctx.Outputs[node.NodeId] = result;
ctx.Log($"[DESERIALIZE] Model \"{targetType}\" not found, returning raw object.");
}
}
}
catch (Exception ex)
{
ctx.Log($"[DESERIALIZE] ERROR: {ex.Message}", logType.Error);
}
}
private static string[] LoadModelProperties(string modelName, ExecutionContext ctx)
{
var modelPath = Path.Combine(ProjectManager.ProjectDirectory, "CustomModels", modelName + ".cs");
if (!File.Exists(modelPath)) return null;
var lines = File.ReadAllLines(modelPath);
var props = lines
.Select(l => l.Trim())
.Where(l => l.StartsWith("public ") && l.Contains("{ get;"))
.Select(l =>
{
var parts = l.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
return parts.Length >= 3 ? parts[2] : null;
})
.Where(p => p != null)
.ToArray();
ctx.Log($"[DESERIALIZE] Loaded model \"{modelName}\": {string.Join(", ", props)}");
return props;
}
private static JObject ProjectToModel(JToken token, string[] modelProps)
{
var source = token as JObject;
if (source == null) return null;
if (source.Count == 1)
{
var first = source.Properties().First();
if (first.Value is JObject inner)
source = inner;
}
var result = new JObject();
foreach (var propName in modelProps)
{
var match = source.Properties()
.FirstOrDefault(p => string.Equals(p.Name, propName, StringComparison.OrdinalIgnoreCase));
result[propName] = match != null ? match.Value.DeepClone() : JValue.CreateNull();
}
return result;
}
private static JArray FindArray(JToken token)
{
if (token is JArray arr) return arr;
if (token is JObject obj)
{
foreach (var prop in obj.Properties())
if (prop.Value is JArray innerArr) return innerArr;
foreach (var prop in obj.Properties())
if (prop.Value is JObject inner)
foreach (var innerProp in inner.Properties())
if (innerProp.Value is JArray deepArr) return deepArr;
}
return null;
}
private static JObject FindObject(JToken token)
{
if (token is JObject obj)
{
var props = obj.Properties().ToList();
if (props.Count == 1 && props[0].Value is JObject inner)
return inner;
return obj;
}
return null;
}
}
internal sealed class ForEachHandler : INodeExecutionHandler
{
public bool CanHandle(OperationViewModel node, ExecutionContext ctx)