2024-10-31 23:32:12 +08:00

382 lines
13 KiB
C#

using System.Data;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace DataSetJsonConverter
{
public class DataSetTest
{
public DataSetTest()
{
Person p1 = new(1, "YES", DateTime.Now);
Person p2 = new(2, "NO", DateTime.Now);
var options = new JsonSerializerOptions()
{
WriteIndented = true
};
options.Converters.Add(new DataSetConverter());
options.Converters.Add(new DateTimeConverter());
var jsonString = JsonSerializer.Serialize(p1, options);
jsonString += JsonSerializer.Serialize(p2, options);
jsonString = "[" + jsonString.Replace("}{", "},{") + "]";
Person[] people = JsonSerializer.Deserialize<Person[]>(jsonString, options) ?? [];
foreach (var person in people)
{
Console.WriteLine(person.Name);
}
}
}
public class DataSetConverter : JsonConverter<DataSet>
{
private readonly string _format = "yyyy-MM-dd hh:mm:ss.fff";
public override DataSet Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dataSet = new DataSet();
var dataTable = new DataTable();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propertyName = reader.GetString() ?? "";
switch (propertyName)
{
case "TableName":
reader.Read();
string tableName = reader.GetString() ?? "";
dataTable = new DataTable(tableName);
dataSet.Tables.Add(dataTable);
break;
case "Columns":
reader.Read();
ReadColumns(reader, dataTable);
break;
case "Rows":
reader.Read();
ReadRows(reader, dataTable);
break;
}
}
}
return dataSet;
}
public override void Write(Utf8JsonWriter writer, DataSet value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString("TableName", value.Tables[0].TableName);
writer.WritePropertyName("Columns");
writer.WriteStartArray();
foreach (DataColumn column in value.Tables[0].Columns)
{
writer.WriteStartObject();
writer.WriteString("ColumnName", column.ColumnName);
writer.WriteString("DataType", column.DataType.FullName);
writer.WriteEndObject();
}
writer.WriteEndArray();
writer.WritePropertyName("Rows");
writer.WriteStartArray();
foreach (DataRow row in value.Tables[0].Rows)
{
writer.WriteStartArray();
for (int i = 0; i < value.Tables[0].Columns.Count; i++)
{
var rowValue = row[i];
switch (value.Tables[0].Columns[i].DataType.FullName)
{
case "System.Boolean":
writer.WriteBooleanValue((bool)rowValue);
break;
case "System.Byte":
writer.WriteNumberValue((byte)rowValue);
break;
case "System.Char":
writer.WriteStringValue(value.ToString());
break;
case "System.DateTime":
writer.WriteStringValue(((DateTime)rowValue).ToString(_format));
break;
case "System.Decimal":
writer.WriteNumberValue((decimal)rowValue);
break;
case "System.Double":
writer.WriteNumberValue((double)rowValue);
break;
case "System.Guid":
writer.WriteStringValue(value.ToString());
break;
case "System.Int16":
writer.WriteNumberValue((short)rowValue);
break;
case "System.Int32":
writer.WriteNumberValue((int)rowValue);
break;
case "System.Int64":
writer.WriteNumberValue((long)rowValue);
break;
case "System.SByte":
writer.WriteNumberValue((sbyte)rowValue);
break;
case "System.Single":
writer.WriteNumberValue((float)rowValue);
break;
case "System.String":
writer.WriteStringValue((string)rowValue);
break;
case "System.UInt16":
writer.WriteNumberValue((ushort)rowValue);
break;
case "System.UInt32":
writer.WriteNumberValue((uint)rowValue);
break;
case "System.UInt64":
writer.WriteNumberValue((ulong)rowValue);
break;
}
}
writer.WriteEndArray();
}
writer.WriteEndArray();
writer.WriteEndObject();
}
private void ReadColumns(Utf8JsonReader reader, DataTable dataTable)
{
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
if (reader.TokenType == JsonTokenType.StartObject)
{
var column = new DataColumn();
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propertyName = reader.GetString() ?? "";
switch (propertyName)
{
case "ColumnName":
reader.Read();
column.ColumnName = reader.GetString();
break;
case "DataType":
reader.Read();
Type dataType = Type.GetType(reader.GetString() ?? "") ?? typeof(string);
column.DataType = dataType;
break;
}
}
if (reader.TokenType == JsonTokenType.EndObject)
{
break;
}
}
dataTable.Columns.Add(column);
}
}
}
private void ReadRows(Utf8JsonReader reader, DataTable dataTable)
{
var values = new object[dataTable.Columns.Count];
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
if (reader.TokenType == JsonTokenType.StartArray)
{
int index = 0;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray)
{
break;
}
switch (dataTable.Columns[index].DataType.ToString())
{
case "System.Boolean":
values[index] = reader.GetBoolean();
break;
case "System.Byte":
values[index] = reader.GetByte();
break;
case "System.Char":
values[index] = (reader.GetString() ?? "")[0];
break;
case "System.DateTime":
string dateString = reader.GetString() ?? "";
if (DateTime.TryParseExact(dateString, _format, null, System.Globalization.DateTimeStyles.None, out DateTime result))
{
values[index] = result;
}
break;
case "System.Decimal":
values[index] = reader.GetDecimal();
break;
case "System.Double":
values[index] = reader.GetDouble();
break;
case "System.Guid":
values[index] = Guid.Parse(reader.GetString() ?? "");
break;
case "System.Int16":
values[index] = reader.GetInt16();
break;
case "System.Int32":
values[index] = reader.GetInt32();
break;
case "System.Int64":
values[index] = reader.GetInt64();
break;
case "System.SByte":
values[index] = reader.GetSByte();
break;
case "System.Single":
values[index] = reader.GetSingle();
break;
case "System.String":
values[index] = reader.GetString() ?? "";
break;
case "System.UInt16":
values[index] = reader.GetUInt16();
break;
case "System.UInt32":
values[index] = reader.GetUInt32();
break;
case "System.UInt64":
values[index] = reader.GetUInt64();
break;
}
index++;
}
dataTable.Rows.Add(values);
}
}
}
}
public class DateTimeConverter : JsonConverter<DateTime>
{
private readonly string _format = "yyyy-MM-dd hh:mm:ss.fff";
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.String)
{
throw new JsonException();
}
string dateString = reader.GetString() ?? "";
if (DateTime.TryParseExact(dateString, _format, null, System.Globalization.DateTimeStyles.None, out DateTime result))
{
return result;
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(_format));
}
}
public class Person
{
public int ID { get; }
public string Name { get; }
public DateTime Time { get; }
public DataSet ds { get; }
[JsonConstructor]
public Person(int ID, string Name, DateTime Time)
{
this.ID = ID;
this.Name = Name;
this.Time = Time;
ds = new DataSet();
var dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Time", typeof(DateTime));
var dr = dt.NewRow();
dr["ID"] = ID;
dr["Name"] = Name;
dr["Time"] = Time;
dt.Rows.Add(dr);
ds.Tables.Add(dt);
}
}
}