- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我需要将大型数据集写入网页(使用服务器端呈现),页面中运行的 JavaScript 组件将使用这些数据集。此数据由数据网格组件和图表组件的对象数组组成(因此每个数组元素都是一个数据网格行)。
出于性能原因,我想使用 JavaScript 对象构造函数而不是对象字面量(有针对使用构造函数的对象的 JIT 编译器优化,并且由于省略了属性名称,它们在线使用的空间更少)。我也可以在本地使用 Date
构造函数。
这是我现在的做法:
<script type="text/javascript">
function WeeklySalesRow( weekName, date, totalSales, profit, loss, turnover, deltaSalesPercentage, etc )
{
this.weekName = weekName;
this.date = date;
this.totalSales = totalSales;
this.profit = profit;
this.loss = loss;
// etc
}
var weeklySalesData = [
@{
Boolean first = true;
foreach( WeeklySalesRow row in this.Model.WeeklySalesData ) {
if( !first ) this.WriteLine( "," ); first = false;
this.Write( "new WeeklySalesRow( \"{0}\", new Date({1}), {2}, {3}, {4}, etc )", row.WeekName, row.Date.ToUnixTimestamp(), row.TotalSales, row.Profit, row.Loss, row.Turnover, etc );
}
}
];
function onDomContentLoaded( e ) {
var chartCompoennt = ...
chartComponent.loadData( weeklySalesData );
}
</script>
像这样呈现:
// [...]
var weeklySalesData = [
new WeeklySalesRow( "2018W1", new Date(1514764800), 1100, 200, 900, 50, 0.56, etc ),
new WeeklySalesRow( "2018W2", new Date(1515369600), 1200, 100, 800, 45, 0.80, etc ),
new WeeklySalesRow( "2018W3", new Date(1515974400), 1300, 50, 700, 65, 0.12, etc ),
new WeeklySalesRow( "2018W4", new Date(1516752000), 1400, 25, 600, 80, 0.45, etc ),
new WeeklySalesRow( "2018W5", new Date(1517443200), 1500, 12, 500, 90, 0.123, etc ),
// etc...
];
// [...]
哪个更简洁:
var weeklySalesData = [
{ weekName: "2018W1", date: "2018-01-01", totalSales: 1100, profit: 200, loss: 900, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W2", date: "2018-01-08", totalSales: 1200, profit: 100, loss: 800, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W3", date: "2018-01-17", totalSales: 1300, profit: 50, loss: 700, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W4", date: "2018-01-23", totalSales: 1400, profit: 25, loss: 600, turnover: 50, deltaSalesPercentage: 0.56, etc },
{ weekName: "2018W5", date: "2018-02-01", totalSales: 1500, profit: 12, loss: 500, turnover: 50, deltaSalesPercentage: 0.56, etc },
];
我知道能够直接解析 JSON 的运行时组件(例如 fetch
和 XMLHttpRequest
)能够减轻使用对象字面量带来的某些性能危害符号(例如,解析器检查数组并发现所有对象文字共享同一组属性名称,因此可以在运行时为它们定义一个内部隐藏基类)——但这种优化不适用于这种情况,因为数据正在呈现到 SSR 网页中,我知道即使是最近的性能基准也没有为“所有数组元素看起来相似”的场景显示任何解析器或编译器优化。
有没有办法让 Json.NET 自动为我做这件事,使用反射自动生成 JavaScript 构造函数和 JavaScript 构造函数调用?
最佳答案
无法完全自动执行此操作,但您可以使用 custom JsonConverter
来完成那叫 JsonWriter.WriteStartConstructor(string name)
及以后 JsonWriter.WriteEndCOnstructor()
.参见 When using a JsonWriter, what's the purpose of WriteStartConstructor? 了解详情。通过使用 .Net 反射或 serializer.ContractResolver
返回的 Json.NET 缓存元数据,可以使自定义转换器通用。 ,但如果是,则需要一些方法来确定构造函数参数顺序。
例如,说你的类型 WeeklySalesData
看起来像下面这样:
public class WeeklySalesData
{
string weekName;
DateTime date;
decimal totalSales;
// If WeeklySalesData had multiple constructors, you could mark the one to use as follows:
// [JsonConstructor]
public WeeklySalesData(string weekName, DateTime date, decimal totalSales)
{
this.weekName = weekName;
this.date = date;
this.totalSales = totalSales;
}
public string WeekName { get { return weekName; } }
public DateTime Date { get { return date; } }
public decimal TotalSales { get { return totalSales; } }
}
请注意,它有一个参数化构造函数,Json.NET 将使用该构造函数在反序列化期间构造类型。要使用构造函数格式序列化此类类型,首先引入以下转换器:
public class ConstructorConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(T) == objectType;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var contract = serializer.ContractResolver.ResolveContract(value.GetType()) as JsonObjectContract;
if (contract == null)
throw new JsonSerializationException(string.Format("Type {0} does not correspond to a JSON object.", value.GetType()));
// Possibly check whether JsonObjectAttribute is applied, and use JsonObjectAttribute.Title if present.
writer.WriteStartConstructor(value.GetType().Name);
foreach (var provider in contract.GetConstructorParameterValueProviders())
{
serializer.Serialize(writer, provider.GetValue(value));
}
writer.WriteEndConstructor();
}
}
public static partial class JsonExtensions
{
internal static IEnumerable<IValueProvider> GetConstructorParameterValueProviders(this JsonObjectContract contract)
{
return contract.CreatorParameters.Select(p => contract.GetConstructorParameterValueProvider(p)).ToArray();
}
internal static IValueProvider GetConstructorParameterValueProvider(this JsonObjectContract contract, JsonProperty parameter)
{
if (parameter.ValueProvider != null)
return parameter.ValueProvider;
var property = contract.Properties.GetClosestMatchProperty(parameter.PropertyName);
var provider = property == null ? null : property.ValueProvider;
if (provider == null)
throw new JsonSerializationException(string.Format("Cannot get IValueProvider for {0}", parameter));
return provider;
}
}
然后使用以下转换器序列化:
var data = new WeeklySalesData("2018W1", new DateTime(2019, 2, 15, 0, 0, 0, DateTimeKind.Utc), 1100);
var settings = new JsonSerializerSettings
{
Converters = { new JavaScriptDateTimeConverter(), new ConstructorConverter<WeeklySalesData>() },
};
var json = JsonConvert.SerializeObject(new [] { data }, Formatting.Indented, settings);
结果是:
[
new WeeklySalesData(
"2018W1",
new Date(
1550188800000
),
1100.0
)
]
注意事项:
Newtonsoft 的 JavaScriptDateTimeConverter
序列化 DateTime
自 1970 年 1 月 1 日 00:00:00 UTC 以来具有构造函数参数值的构造函数,与 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date 一致.您似乎使用不同的单位进行序列化,可能是秒而不是毫秒。
如果您的类型没有参数化构造函数,您可以使用一些其他机制(例如 data member order)指定 JavaScript 构造函数参数顺序。或 JsonPropertyAttribute.Order .然后可以从 JsonObjectContract.Properties
中按顺序获取构造函数参数集合,使用与 ObjectToArrayConverter<T>.WriteJson()
相同的算法来自 this answer给 C# JSON.NET - Deserialize response that uses an unusual data structure 。
我没有尝试实现反序列化,因为没有人要求它。
演示 fiddle here .
关于javascript - 我可以使用 Json.NET 将对象序列化为 JavaScript 构造函数调用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54759586/
我正在阅读 Python 文档以真正深入了解 Python 语言,并遇到了 filter 和 map 函数。我以前使用过过滤器,但从未使用过映射,尽管我在 SO 上的各种 Python 问题中都见过这
当我尝试打印 BST 的级别顺序时,这个问题提示了我。 这是一个 Pre-Order Sequence: 4, 1, 2, 3, 5, 6, 7, 8 In_order Sequence : 1, 2
我的代码在 main(序列测试;)的第一行出现错误,指出它是对 sequence::sequence() 的 undefined reference 。我无法更改 main 中的代码。有谁知道我该如何
这可能很简单,但我在通常的 latex 指南中找不到任何相关内容。在这句话中: {\em hello\/} “\/”的目的是什么? 最佳答案 这就是所谓的斜体校正。其目的是确保斜体文本后有适当的间距。
当我从 Postgresql 表中删除所有记录,然后尝试重置序列以在插入时开始一个编号为 1 的新记录时,我得到不同的结果: SELECT setval('tblname_id_seq', (SELE
在版本10.0.3中,MariaDB引入了一种称为序列的存储引擎。 其ad hoc为操作生成整数序列,然后终止。 该序列包含正整数,以降序或升序排列,并使用起始,结束和递增值。 它不允许在多个查询中
如何在 Groovy 中获取给定数字的序列,例如: def number = 169 // need a method in groovy to find the consecutive number
基本上,如果这是 .NET,它看起来像这样: ISomething { string A { get; } int B { get; } } var somethings = new List
说以下代码部分(同一块): A <= 1 A <= 2 变量 A 总是被赋值为 2 吗?还是会出现竞争条件并分配 1 或 2? 我对非阻塞赋值的理解是,由硬件在 future 分配变量 A,因此它可能
在运行 WiX 设置时,我正在寻找操作列表及其顺序。不知何故,官方网站似乎没有提供任何信息。 基本问题是我想正确安排我的自定义操作。通常我需要使用 regsvr32.exe 注册一个 DLL,而这只能
F#初学者在这里 我想创建一个类型,它是具有至少一个元素的另一种具体类型(事件)的序列。任何其他元素都可以在以后随时添加。通常在 C# 中,我会创建一个具有私有(private) List 和公共(p
作为构建过程和不断发展的数据库的一部分,我试图创建一个脚本,该脚本将删除用户的所有表和序列。我不想重新创建用户,因为这将需要比所允许的更多的权限。 我的脚本创建了一个过程来删除表/序列,执行该过程,然
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
这个问题已经有答案了: sql ORDER BY multiple values in specific order? (12 个回答) 已关闭 9 年前。 我有一个 sql 语句,我想要ORDER
我想恢复两个向量的第一个日期和相同向量的第二个日期之间的日期序列,.... 这是一个例子: dates1 = as.Date(c('2015-10-01', '2015-03-27', '2015-0
在用java编写代码时,我需要用“],[”分割字符串。下面是我的代码。 try (BufferedReader reader = new BufferedReader(new InputStreamR
这个问题已经有答案了: Project Euler Question 14 (Collatz Problem) (8 个回答) 已关闭 9 年前。 我正在尝试查找数字的 Collatz 序列。以下
我有一个例程函数process_letter_location(const char& c, string &word)。 在我的 main 中,我声明了一系列字符串变量,如下所示: string s
我需要找到最长的多米诺骨牌链,给定一组 12 个随机挑选的多米诺骨牌。我已经递归地生成了多米诺骨牌的所有可能性(使用 0 到 12 的面值有 91 种可能性)。多米诺骨牌由一 block “砖 blo
我有这个数据结构 Seq,它继承了类 vector 但有一些额外的功能。使用这个数据结构 Seq 我有这个预定义的数据结构: typedef Seq > MxInt2d; 我现在想要一个包含多个 Mx
我是一名优秀的程序员,十分优秀!