JsonSerializer重寫Convert以解決數值類型數據的轉化問題


當json數據為 "{\"Data\":[{\"abc\":50},{\"abc\":50.01}]}"時,轉換成DataTable會導致abc列被認定為Int類型。第二條數據的50.01會被轉換成50,導致數據有問題。

處理方式是重寫轉換器,把INT類型的字段用Double類型來代替。避免數據精度丟失。

public class CustomDataTableConverter : DataTableConverter
{
    private static void CreateRow(JsonReader reader, DataTable dt)
    {
        DataRow row = dt.NewRow();
        reader.Read();
        while(reader.TokenType == JsonToken.PropertyName)
        {
            string columnName = (string)reader.Value;
            reader.Read();
            DataColumn column = dt.Columns[columnName];
            if(column == null)
            {
                Type columnDataType = GetColumnDataType(reader);
                column = new DataColumn(columnName, columnDataType);
                dt.Columns.Add(column);
            }
            if(column.DataType == typeof(DataTable))
            {
                if(reader.TokenType == JsonToken.StartArray)
                {
                    reader.Read();
                }
                DataTable table = new DataTable();
                while(reader.TokenType != JsonToken.EndArray)
                {
                    CreateRow(reader, table);
                    reader.Read();
                }
                row[columnName] = table;
            }
            else if(column.DataType.IsArray && (column.DataType != typeof(byte[])))
            {
                if(reader.TokenType == JsonToken.StartArray)
                {
                    reader.Read();
                }
                List<object> list = new List<object>();
                while(reader.TokenType != JsonToken.EndArray)
                {
                    list.Add(reader.Value);
                    reader.Read();
                }
                Array destinationArray = Array.CreateInstance(column.DataType.GetElementType(), list.Count);
                Array.Copy(list.ToArray(), destinationArray, list.Count);
                row[columnName] = destinationArray;
            }
            else
            {
                row[columnName] = reader.Value ?? DBNull.Value;
            }
            reader.Read();
        }
        row.EndEdit();
        dt.Rows.Add(row);
    }

    private static Type GetColumnDataType(JsonReader reader)
    {
        JsonToken tokenType = reader.TokenType;
        switch(tokenType)
        {
            case JsonToken.StartArray:
                reader.Read();
                if(reader.TokenType != JsonToken.StartObject)
                {
                    return GetColumnDataType(reader).MakeArrayType();
                }
                return typeof(DataTable);
            case JsonToken.Integer:
                return typeof(double); //在此特殊處理int類型
            case JsonToken.Float:
            case JsonToken.String:
            case JsonToken.Boolean:
            case JsonToken.Date:
            case JsonToken.Bytes:
                return reader.ValueType;
            case JsonToken.Null:
            case JsonToken.Undefined:
                return typeof(string);
        }
        throw new JsonException(string.Format("Unexpected Json token while reading DataTable: {0}", tokenType));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        DataTable dt = existingValue as DataTable;
        if(dt == null)
        {
            dt = (objectType == typeof(DataTable)) ? new DataTable() : ((DataTable)Activator.CreateInstance(objectType));
        }
        if(reader.TokenType == JsonToken.PropertyName)
        {
            dt.TableName = (string)reader.Value;
            reader.Read();
        }
        if(reader.TokenType == JsonToken.StartArray)
        {
            reader.Read();
        }
        while(reader.TokenType != JsonToken.EndArray)
        {
            CreateRow(reader, dt);
            reader.Read();
        }
        return dt;
    }
     
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        DataTable table = (DataTable)value;
        DefaultContractResolver contractResolver = serializer.ContractResolver as DefaultContractResolver;
        writer.WriteStartArray();
        foreach(DataRow row in table.Rows)
        {
            writer.WriteStartObject();
            foreach(DataColumn column in row.Table.Columns)
            {
                if((serializer.NullValueHandling != NullValueHandling.Ignore) || ((row[column] != null) && (row[column] != DBNull.Value)))
                {
                    writer.WritePropertyName((contractResolver != null) ? contractResolver.GetResolvedPropertyName(column.ColumnName) : column.ColumnName);
                    serializer.Serialize(writer, row[column]);
                }
            }
            writer.WriteEndObject();
        }
        writer.WriteEndArray();
    }
}

            
調用方式:
//
JObject jo JsonSerializer serializer = new JsonSerializer(); serializer.Converts.Add(new CustomDataTableConverter()); DataTable dt = jo.GetValue("Data").ToObject<DataTable>(serializer);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM