c# - convert - newtonsoft json serialize vb net
DataTable a JSON (3)
Recientemente necesité serializar una tabla de datos a JSON. Donde estoy todavía estamos en .Net 2.0, así que no puedo usar el serializador JSON en .Net 3.5. Pensé que esto debía haberse hecho antes, así que busqué en línea y encontré varias opciones diferentes . Algunos de ellos dependen de una biblioteca adicional, que me resultaría difícil adelantar aquí. Otros requieren primero la conversión a List<Dictionary<>>
, lo que parecía un poco incómodo e innecesario. Otro trató todos los valores como una cadena. Por una razón u otra, no podía realmente estar detrás de ninguno de ellos, así que decidí lanzar el mío, que se publica a continuación.
Como puede ver leyendo los comentarios //TODO
, está incompleto en algunos lugares. Este código ya está en producción aquí, por lo que "funciona" en el sentido básico. Los lugares donde está incompleto son los lugares donde sabemos que nuestros datos de producción no lo afectarán (sin timespans o arrays de bytes en el db). La razón por la que estoy publicando aquí es porque siento que esto puede ser un poco mejor, y me gustaría ayudar a terminar y mejorar este código. Cualquier entrada de bienvenida.
Tenga en cuenta que esta capacidad está integrada en .Net 3.5 y posterior, por lo que la única razón para utilizar este código hoy es si todavía está limitado a .Net 2.0. Incluso entonces, JSON.Net se ha convertido en la biblioteca goto para este tipo de cosas.
public static class JSONHelper
{
public static string FromDataTable(DataTable dt)
{
string rowDelimiter = "";
StringBuilder result = new StringBuilder("[");
foreach (DataRow row in dt.Rows)
{
result.Append(rowDelimiter);
result.Append(FromDataRow(row));
rowDelimiter = ",";
}
result.Append("]");
return result.ToString();
}
public static string FromDataRow(DataRow row)
{
DataColumnCollection cols = row.Table.Columns;
string colDelimiter = "";
StringBuilder result = new StringBuilder("{");
for (int i = 0; i < cols.Count; i++)
{ // use index rather than foreach, so we can use the index for both the row and cols collection
result.Append(colDelimiter).Append("/"")
.Append(cols[i].ColumnName).Append("/":")
.Append(JSONValueFromDataRowObject(row[i], cols[i].DataType));
colDelimiter = ",";
}
result.Append("}");
return result.ToString();
}
// possible types:
// http://msdn.microsoft.com/en-us/library/system.data.datacolumn.datatype(VS.80).aspx
private static Type[] numeric = new Type[] {typeof(byte), typeof(decimal), typeof(double),
typeof(Int16), typeof(Int32), typeof(SByte), typeof(Single),
typeof(UInt16), typeof(UInt32), typeof(UInt64)};
// I don''t want to rebuild this value for every date cell in the table
private static long EpochTicks = new DateTime(1970, 1, 1).Ticks;
private static string JSONValueFromDataRowObject(object value, Type DataType)
{
// null
if (value == DBNull.Value) return "null";
// numeric
if (Array.IndexOf(numeric, DataType) > -1)
return value.ToString(); // TODO: eventually want to use a stricter format. Specifically: separate integral types from floating types and use the "R" (round-trip) format specifier
// boolean
if (DataType == typeof(bool))
return ((bool)value) ? "true" : "false";
// date -- see http://weblogs.asp.net/bleroy/archive/2008/01/18/dates-and-json.aspx
if (DataType == typeof(DateTime))
return "/"///Date(" + new TimeSpan(((DateTime)value).ToUniversalTime().Ticks - EpochTicks).TotalMilliseconds.ToString() + ")////"";
// TODO: add Timespan support
// TODO: add Byte[] support
//TODO: this would be _much_ faster with a state machine
//TODO: way to select between double or single quote literal encoding
//TODO: account for database strings that may have single /r or /n line breaks
// string/char
return "/"" + value.ToString().Replace(@"/", @"//").Replace(Environment.NewLine, @"/n").Replace("/"", @"/""") + "/"";
}
}
Actualizar:
Esto es viejo ahora, pero quería señalar algo sobre cómo maneja este código las fechas. El formato que utilicé tenía sentido en ese momento, por la razón exacta en la url. Sin embargo, ese razonamiento incluye lo siguiente:
Para ser honesto, JSON Schema resuelve el problema al permitir "subtipificar" una cadena como un literal de fecha, pero esto todavía está en progreso y llevará tiempo alcanzar una adopción significativa.
Bueno, el tiempo ha pasado. Hoy, está bien solo usar el formato de fecha ISO 8601 . No voy a molestarme en cambiar el código, porque realmente: esto es antiguo. Solo usa JSON.Net.
¿Te ayudaría a convencer a tus jefes para que instalen una biblioteca si se trata de extensiones AJAX de Microsoft para .NET 2.0 ?
Incluido en ellos está System.Web.Script.Serialization.JavascriptSerializer , que se usa en el Paso 4 del último enlace en su publicación.
Encontré esto: http://www.bramstein.com/projects/xsltjson/ Puede convertir su datatable en xml y usar una hoja de estilo xslt para convertir el xml en json.
Es más una solución que una solución real.
Hola, amigo, está todo aquí en la publicación del blog de Rick Serializing DataTable usando Json.NET . Él explica en detalle cómo puedes lograrlo usando Json.NET de James Newton King .