using Lskj.Util; using Newtonsoft.Json; using System; using System.Data; namespace Lskj.Util.Tests { internal static class Program { private static int Main() { try { PreservesStylesObjectAsCompactJson(); PreservesArrayAsCompactJson(); NormalizesEveryValueInAMixedComplexColumn(); LeavesScalarColumnsEquivalentToExistingConverter(); AcceptsSingleObject(); RejectsInvalidTopLevelValues(); Console.WriteLine("PASS: JsonUtil complex-value conversion tests"); return 0; } catch (Exception ex) { Console.Error.WriteLine(ex); return 1; } } private static void PreservesStylesObjectAsCompactJson() { const string json = "[{\"id\":1,\"$styles\":{\"rowstyle\":\"{color:'#FFFF00','background-color':'#FF0000'}\"}}]"; DataTable table = JsonUtil.ToDataTablePreservingComplexValues(json); AssertEqual(1, table.Rows.Count, "styles row count"); AssertEqual("{\"rowstyle\":\"{color:'#FFFF00','background-color':'#FF0000'}\"}", table.Rows[0]["$styles"].ToString(), "styles JSON"); } private static void PreservesArrayAsCompactJson() { const string json = "[{\"id\":1,\"items\":[{\"code\":\"A\"},{\"code\":\"B\"}]}]"; DataTable table = JsonUtil.ToDataTablePreservingComplexValues(json); AssertEqual("[{\"code\":\"A\"},{\"code\":\"B\"}]", table.Rows[0]["items"].ToString(), "array JSON"); } private static void NormalizesEveryValueInAMixedComplexColumn() { const string json = "[" + "{\"id\":1,\"payload\":5}," + "{\"id\":2,\"payload\":{\"code\":\"A\"}}," + "{\"id\":3,\"payload\":[1,2]}," + "{\"id\":4,\"payload\":null}," + "{\"id\":5,\"payload\":\"ready\"}]"; DataTable table = JsonUtil.ToDataTablePreservingComplexValues(json); AssertEqual(typeof(string), table.Columns["payload"].DataType, "mixed column type"); AssertEqual("5", table.Rows[0]["payload"].ToString(), "numeric scalar text"); AssertEqual("{\"code\":\"A\"}", table.Rows[1]["payload"].ToString(), "object text"); AssertEqual("[1,2]", table.Rows[2]["payload"].ToString(), "array text"); AssertTrue(table.Rows[3].IsNull("payload"), "null remains null"); AssertEqual("ready", table.Rows[4]["payload"].ToString(), "string remains string"); } private static void LeavesScalarColumnsEquivalentToExistingConverter() { const string json = "[{\"id\":1,\"title\":\"A\",\"active\":true},{\"id\":2,\"title\":\"B\",\"active\":false}]"; DataTable expected = JsonConvert.DeserializeObject(json); DataTable actual = JsonUtil.ToDataTablePreservingComplexValues(json); AssertEqual(expected.Columns.Count, actual.Columns.Count, "scalar column count"); AssertEqual(expected.Rows.Count, actual.Rows.Count, "scalar row count"); foreach (DataColumn column in expected.Columns) { AssertEqual(column.DataType, actual.Columns[column.ColumnName].DataType, "scalar column type " + column.ColumnName); for (int rowIndex = 0; rowIndex < expected.Rows.Count; rowIndex++) { AssertEqual(expected.Rows[rowIndex][column.ColumnName], actual.Rows[rowIndex][column.ColumnName], "scalar value " + column.ColumnName + " row " + rowIndex); } } } private static void AcceptsSingleObject() { const string json = "{\"ProductId\":\"P001\",\"meta\":{\"source\":\"web\"}}"; DataTable table = JsonUtil.ToDataTablePreservingComplexValues(json); AssertEqual(1, table.Rows.Count, "single object row count"); AssertEqual("P001", table.Rows[0]["ProductId"].ToString(), "single object scalar"); AssertEqual("{\"source\":\"web\"}", table.Rows[0]["meta"].ToString(), "single object nested JSON"); } private static void RejectsInvalidTopLevelValues() { AssertThrows(delegate { JsonUtil.ToDataTablePreservingComplexValues(" "); }, "empty input"); AssertThrows(delegate { JsonUtil.ToDataTablePreservingComplexValues("{"); }, "invalid JSON"); AssertThrows(delegate { JsonUtil.ToDataTablePreservingComplexValues("[1]"); }, "non-object row"); } private static void AssertThrows(Action action, string name) where TException : Exception { try { action(); } catch (TException) { return; } throw new InvalidOperationException("Expected " + typeof(TException).Name + ": " + name); } private static void AssertTrue(bool value, string name) { if (!value) throw new InvalidOperationException("Assertion failed: " + name); } private static void AssertEqual(T expected, T actual, string name) { if (!object.Equals(expected, actual)) { throw new InvalidOperationException(name + ": expected <" + expected + ">, actual <" + actual + ">"); } } } }