内容目录
后面改进了对象池算法,使用结构体来存储,其性能变得非常强。
参考对象池算法:https://www.whuanle.cn/archives/20888
新版本
定义结构体存储每个字段:
public struct JsonField
{
public string? Name
{
get; set;
}
public JsonValueKind ValueKind
{
get; set;
}
public object? Value
{
get; set;
}
public string? Key
{
get; set;
}
}
定义静态类:
public static class JsonParseTool
{
}
解析字段:
// 解析 json 字段
private static object? ReadObject(ref Utf8JsonReader reader, ref JsonField field)
{
switch (reader.TokenType)
{
case JsonTokenType.Null or JsonTokenType.None:
field.ValueKind = JsonValueKind.Null;
return null;
case JsonTokenType.False:
field.ValueKind = JsonValueKind.False;
return reader.GetBoolean();
case JsonTokenType.True:
field.ValueKind = JsonValueKind.True;
return reader.GetBoolean();
case JsonTokenType.Number:
field.ValueKind = JsonValueKind.Number;
return reader.GetDouble();
case JsonTokenType.String:
field.ValueKind = JsonValueKind.String;
return reader.GetString() ?? "";
default: return null;
}
}
解析数组:
private static void ParseArray(ObjectPool pool,
ref Utf8JsonReader reader,
Dictionary<string, JsonField> map,
string? baseKey)
{
var i = 0;
while (reader.Read())
{
if (reader.TokenType is JsonTokenType.EndArray) break;
var newkey = baseKey is null ? $"[{i}]" : $"{baseKey}[{i}]";
i++;
ref var field = ref pool.Get();
field.Key = newkey;
map[newkey] = field;
switch (reader.TokenType)
{
// [...,null,...]
case JsonTokenType.Null:
field.ValueKind = JsonValueKind.Null;
break;
// [...,123.666,...]
case JsonTokenType.Number:
field.ValueKind = JsonValueKind.Number;
field.Value = reader.GetDouble();
break;
// [...,"123",...]
case JsonTokenType.String:
field.ValueKind = JsonValueKind.String;
field.Value = reader.GetString();
break;
// [...,true,...]
case JsonTokenType.True:
field.ValueKind = JsonValueKind.True;
field.Value = reader.GetBoolean();
break;
case JsonTokenType.False:
field.ValueKind = JsonValueKind.False;
field.Value = reader.GetBoolean();
break;
// [...,{...},...]
case JsonTokenType.StartObject:
field.ValueKind = JsonValueKind.Object;
BuildJsonField(pool, ref reader, ref field, map, newkey);
break;
// [...,[],...]
case JsonTokenType.StartArray:
field.ValueKind = JsonValueKind.Array;
ParseArray(pool, ref reader, map, newkey);
break;
default:
field.ValueKind = JsonValueKind.Null;
break;
}
}
}
解析对象:
private static void BuildJsonField(
ObjectPool pool,
ref Utf8JsonReader reader,
ref JsonField root,
Dictionary<string, JsonField> map,
string? baseKey)
{
while (reader.Read())
{
// 顶级数组 "[123,123]"
if (reader.TokenType is JsonTokenType.StartArray)
{
root.Key = baseKey;
root.ValueKind = JsonValueKind.Array;
ParseArray(pool, ref reader, map, baseKey);
}
else if (reader.TokenType is JsonTokenType.EndObject) break;
else if (reader.TokenType is JsonTokenType.PropertyName)
{
var key = reader.GetString()!;
var newkey = baseKey is null ? key : $"{baseKey}.{key}";
ref JsonField field = ref pool.Get();
field.Name = key;
field.Key = newkey;
map[newkey] = field;
reader.Read();
if (reader.TokenType is JsonTokenType.StartArray)
{
field.ValueKind = JsonValueKind.Array;
// 进入数组处理
ParseArray(pool, ref reader, map, newkey);
}
else if (reader.TokenType is JsonTokenType.StartObject)
{
field.ValueKind = JsonValueKind.Object;
BuildJsonField(pool, ref reader, ref field, map, newkey);
}
else
{
field.Value = ReadObject(ref reader, ref field);
}
}
}
}
进入解析:
public static Dictionary<string, JsonField> Read(
JsonFieldMemoryPool memoryPool,
ReadOnlySequence<byte> sequence,
JsonReaderOptions jsonReaderOptions)
{
var reader = new Utf8JsonReader(sequence, jsonReaderOptions);
var map = new Dictionary<string, JsonField>();
ref JsonField root = ref memoryPool.Get();
root.ValueKind = JsonValueKind.Object;
map["/"] = root;
BuildJsonField(memoryPool, ref reader, ref root, map, null);
return map;
}
旧版本
下面用到一个对象池算法,类型 JsonFieldMemoryPool
,也可以改成 new Object
的方式。
每个字段的模型:
public record JsonField
{
public string? Name { get; set; }
public JsonValueKind ValueKind { get; set; }
public object? Value { get; set; }
public string? Key { get; set; }
}
解析一个字段:
// 解析 json 字段
private static object? ReadObject(ref Utf8JsonReader reader, JsonField field)
{
switch (reader.TokenType)
{
case JsonTokenType.Null or JsonTokenType.None:
field.ValueKind = JsonValueKind.Null;
return null;
case JsonTokenType.False:
field.ValueKind = JsonValueKind.False;
return reader.GetBoolean();
case JsonTokenType.True:
field.ValueKind = JsonValueKind.True;
return reader.GetBoolean();
case JsonTokenType.Number:
field.ValueKind = JsonValueKind.Number;
return reader.GetDouble();
case JsonTokenType.String:
field.ValueKind = JsonValueKind.String;
return reader.GetString() ?? "";
default: return null;
}
}
解析数组:
private static void ParseArray(JsonFieldMemoryPool pool,
ref Utf8JsonReader reader,
Dictionary<string, JsonField> map,
string? baseKey)
{
int i = 0;
while (reader.Read())
{
if (reader.TokenType is JsonTokenType.EndArray) break;
var newkey = baseKey is null ? $"[{i}]" : $"{baseKey}[{i}]";
i++;
var field = pool.Get();
field.Key = newkey;
map[newkey] = field;
switch (reader.TokenType)
{
// [...,null,...]
case JsonTokenType.Null:
field.ValueKind = JsonValueKind.Null;
break;
// [...,123.666,...]
case JsonTokenType.Number:
field.ValueKind = JsonValueKind.Number;
field.Value = reader.GetDouble();
break;
// [...,"123",...]
case JsonTokenType.String:
field.ValueKind = JsonValueKind.String;
field.Value = reader.GetString();
break;
// [...,true,...]
case JsonTokenType.True:
field.ValueKind = JsonValueKind.True;
field.Value = reader.GetBoolean();
break;
case JsonTokenType.False:
field.ValueKind = JsonValueKind.False;
field.Value = reader.GetBoolean();
break;
// [...,{...},...]
case JsonTokenType.StartObject:
field.ValueKind = JsonValueKind.Object;
BuildJsonField(pool, ref reader, field, map, newkey);
break;
// [...,[],...]
case JsonTokenType.StartArray:
field.ValueKind = JsonValueKind.Array;
ParseArray(pool, ref reader, map, newkey);
break;
default:
field.ValueKind = JsonValueKind.Null;
break;
}
}
}
解析对象:
private static void BuildJsonField(
JsonFieldMemoryPool pool,
ref Utf8JsonReader reader,
JsonField root,
Dictionary<string, JsonField> map,
string? baseKey)
{
while (reader.Read())
{
// 顶级数组 "[123,123]"
if (reader.TokenType is JsonTokenType.StartArray)
{
root.Key = baseKey;
root.ValueKind = JsonValueKind.Array;
ParseArray(pool, ref reader, map, baseKey);
}
else if (reader.TokenType is JsonTokenType.EndObject) break;
else if (reader.TokenType is JsonTokenType.PropertyName)
{
var key = reader.GetString()!;
var newkey = baseKey is null ? key : $"{baseKey}.{key}";
JsonField field = pool.Get();
field.Name = key;
field.Key = newkey;
map[newkey] = field;
reader.Read();
if (reader.TokenType is JsonTokenType.StartArray)
{
field.ValueKind = JsonValueKind.Array;
// 进入数组处理
ParseArray(pool, ref reader, map, newkey);
}
else if (reader.TokenType is JsonTokenType.StartObject)
{
field.ValueKind = JsonValueKind.Object;
BuildJsonField(pool, ref reader, field, map, newkey);
}
else
{
field.Value = ReadObject(ref reader, field);
}
}
}
}
进入解析:
public static Dictionary<string, JsonField> Read(
JsonFieldMemoryPool memoryPool,
ReadOnlySequence<byte> sequence,
JsonReaderOptions jsonReaderOptions)
{
var reader = new Utf8JsonReader(sequence, jsonReaderOptions);
var map = new Dictionary<string, JsonField>();
JsonField root = memoryPool.Get();
root.ValueKind = JsonValueKind.Object;
map["/"] = root;
BuildJsonField(memoryPool, ref reader, root, map, null);
return map;
}
文章评论