JsonSerializer.Parse(String, Type, JsonSerializerOptions)
ã¯åçãªExpandoObject
ãªã¿ãŒã³ã¿ã€ãããµããŒãããŠããŸããïŒ
ãã®ãããªãã®ïŒ
dynamic p = JsonSerializer.Parse(json, typeof(ExpandoObject));
ãããããã®æ©èœã¯çŸæç¹ã§ã¯ãµããŒããããŠããŸããããvNextã§æ€èšããå¿ èŠããããŸãã æ©èœãªã¯ãšã¹ããåæ©ä»ããããã®äœ¿çšäŸã¯ãããŸããïŒ
æªæ¥ãšããŠããŒã¯ããŸãã
System.NotSupportedException : The collection type 'System.Dynamic.ExpandoObject' is not supported.
@ahsonkhanGraphQLã¯è¯ãäŸã§ãã
ä»æ§ã§ã¯JSONãæšå¥šããŠããŸãããå¿çã®ç¹å®ã®ã·ãªã¢ã«åã«ã¯é¢é£ä»ããããŠããŸããã
ããã¯ãå¿çã®ãããŒã¿ããã£ãŒã«ããåçã§ãããšããããšãæå³ããŸãã æšæž¬ã§ããªãã®ã§ã
ExpandoObjectããªãå Žåãéã·ãªã¢ã«åã«ããåçã«JSONäœæã®äžçš®ã«ãªããŸãã ãããã£ãŠããã®æœè±¡çãªåçãããŒã¿ããžã®ã¢ã¯ã»ã¹ã¯ãå®éã«ã¯åçãJTokenã§ããããšãèªèããŠè¡ãå¿
èŠããããŸãã
ExpandoObjectã䜿çšãããšãäžè¬çãªãªããžã§ã¯ãã®ããã«åçãªãããŒã¿ããžã®ã¢ã¯ã»ã¹ã匷å¶ã§ãããšæããŸãã
@ahsonkhanå¥ã®äŸã¯ããããžã§ã¯ãã®æ§æãµãŒãã¹ã§ãã ããã¯ãMongoDBã§ã³ã¬ã¯ã·ã§ã³ãäœæããRESTãšã³ããã€ã³ãã®ãããªã³ã¬ã¯ã·ã§ã³ãå ¬éããŸãïŒããã¯åãªããããŒã®RESTã©ãããŒã§ã¯ãªããRESTã³ã¬ã¯ã·ã§ã³ãšmongoã³ã¬ã¯ã·ã§ã³ã«ã¯æ£ç¢ºãª1-1ãããã³ã°ããªããç¹å®ã®ã«ãŒã«ãã¢ãµãŒãããŸãïŒã
ãããã£ãŠãç§ãã¡ã®ãããžã§ã¯ãã§ã¯ãåç/ ExpandoObjectã®ãµããŒããå¿ èŠã§ãã
ä»ã®ãã€ã¯ããµãŒãã¹ã§ã䜿çšããŠããŸãã
ãŸãããã®å¶éã«ééããŸããã ç§ãã¡ã®ãŠãŒã¹ã±ãŒã¹ã¯ãjsonã·ãªã¢ã«åã®åã«åçãªããžã§ã¯ããåŸã ã«æ§ç¯ããŠããŸãã ããæçããJson.NETã·ãªã¢ã©ã€ã¶ãŒã«æ»ããŸããã
ããã¿ããª
ä»ã®ãšããæ£æ©ã¯äœã§ããïŒ
ã©ã¡ãã䜿çšããããæ§æã§ããŸããïŒ
@SidShetyeããªãã¯äœããããæçãããã®ã«æ»ã£ããšèšããŸãããããªãã¯èª¬æããŠããããŸããïŒ
@MickeyReznikov ïŒ https ïŒ //stackoverflow.com/questions/15455304/deserialize-a-property-as-an-expandoobject-using-json-netãŸãã¯googleãjson.netexpandoobjectããåç §ããŠãã ãã
@MickeyReznikov ãããªãã®è³ªåã¯çããããŸãããïŒ @SidShetyeã¯ãNewtonsoft.Json
ã䜿çšããããšãæå³ããŠãããšæããŸãã asp.netã¢ããªã®å Žåã¯ãAddNewtonsoftJsonã«æ»ãããã«æ§æã§ããŸãã
ããã®ãŠãŒã¹ã±ãŒã¹ããããŸããHttpClientã䜿çšããŠRESTAPIãåŒã³åºããå¿çããåäžã®ããããã£ãååŸãããã ãã§ãã å¿çã解æããããã ãã«å°çšã®ã¯ã©ã¹ãäœæããããããŸãã... JSON.NETã䜿çšãããšããåçãã䜿çšããŠãéžæããããããã£ã«ã¢ã¯ã»ã¹ã§ããŸãã
https://github.com/dotnet/corefx/issues/41472ãã@ ghost1372 ïŒ
ããã«ã¡ã¯ç§ã¯ããããã®è³ªåãããã®ã«è¯ãå Žæã§ããããšãé¡ã£ãŠããŸã
åçãªããžã§ã¯ããéã·ãªã¢ã«åã§ããªãããã§ã
ç§ã¯ãã®ã³ãŒãã䜿çšããŸããããæ©èœããŸããã§ãããããè¡ãæ¹æ³ã¯ãããŸããïŒvar objList = System.Text.Json.JsonSerializer.Deserialize<List<dynamic>>(json);
å€ãã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãã¹ãã¢ãããã·ãŒãžã£ããã®ããŒã¿ã®ãã£ãŒã«ããå¶åŸ¡ããjquery.jtableã䜿çšããŠãªã¹ãããŒãžãšæ€çŽ¢ãªã¹ãããŒãžãåçã«ã¬ã³ããªã³ã°ããŠããŸãã
ExpandoObjectã®JsonSerializerçµã¿èŸŒã¿ãµããŒãããªããšãdotnetcoreçµã¿èŸŒã¿Jsonã·ãªã¢ã«åã䜿çšã§ããŸããã
@estillerãš@SidShetyeããã§ã«è¿°ã¹ãã®ãšåããŠãŒã¹ã±ãŒã¹ãå
±æããŠããŸã
ãã®éã«ãJson.NETã«æ»ãå¿
èŠããããŸããã
Futureããã_now_ã«è¿ããã€ã«ã¹ããŒã³ãæã€ããšã¯å¯èœã§ããïŒ ð€
ExpandoObjectã¯é·ãéBCLã«å«ãŸããŠããŸãã
ExpandoObjectã®ä»£æ¿æ段ã¯ãããŸããïŒ
@fatihyildizhanãããã代æ¿æ段ã¯ãããŸããã
ãã ããç¬èªã®ExpandoObjectã³ã³ããŒã¿ãŒãäœæããã®ã§ããã®èšäºãããã³ããåŸãããšãã§ããŸãASP.NET Core 3.0ïŒæ°ããSystem.Text.Jsonã®ã«ã¹ã¿ã JsonConverter
ã·ãªã¢ã«åã®ã¿ãå¿ èŠãªã®ã§ãã·ãªã¢ã«åãäœæããã ãã§ã
ããããŸã ãµããŒããããŠããªãããšã«é©ããŸããã
ããã5.0ã«ç§»åããŸãã
5.0ã«ç§»è¡ããŸããïŒ ã€ãŸããå°ãªããšã1幎ã¯åŸ ããªããã°ãªããªããšããããšã§ããïŒ JSON.Netã«æ»ããŸãã
5.0ïŒ ãããŒãããã¯ééããªãã²ã©ãã§ãã
äžæçãªéãåé¿çãšããŠãã«ã¹ã¿ã ã³ã³ããŒã¿ãŒãåããJsonDocumentã䜿çšã§ããŸãããIDisposableã§ãã
public sealed class EventObject
{
[JsonPropertyName("id")]
public long Id
{
get; set;
}
[JsonPropertyName("eventData")]
[JsonConverter(typeof(JsonDocumentConverter))]
public System.Text.Json.JsonDocument EventData
{
get; set;
}
}
internal sealed class JsonDocumentConverter
: JsonConverter<System.Text.Json.JsonDocument>
{
public override JsonDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return JsonDocument.ParseValue(ref reader);
}
public override void Write(Utf8JsonWriter writer, JsonDocument value, JsonSerializerOptions options)
{
value.WriteTo(writer);
}
}
System.Text.Jsonãååšããå Žåã次ã®POSTã¢ã¯ã·ã§ã³ã䜿çšã§ããªããªããŸãã
[HttpPost]
public async Task<IActionResult> SubmitAsync(dynamic model)
代ããã«ã次ã®æ¹æ³ã䜿çšããå¿ èŠããããŸããããããŠã³ã¹ããªãŒã ã®ããã¯ãšã³ãã³ãŒãã§ãmodelãã䜿çšããã®ã¯ç°¡åã§ã¯ãããŸããã§ããã
[HttpPost]
public async Task<IActionResult> SubmitAsync(JsonElement model)
ãã¢ãã«ãã¯è€éãªãªããžã§ã¯ãã§ããããªããžã§ã¯ãã®ã³ã¬ã¯ã·ã§ã³ããã®ä»ã®ãã¹ããããè€éãªãªããžã§ã¯ããå«ãŸããŠããå ŽåããããŸãã JsonElement
ããdynamic
ãªããžã§ã¯ããçµè«ä»ããããšãã§ããããã«ããã«ã¯ãmodel.GetRawTextïŒïŒãåŒã³åºããNewtonsoftã«ãããåçãªããžã§ã¯ãã«ãã³ãŒããããå¿
èŠããããŸããã ãã®æŒç¿ã®äž»ãªç®çã¯ãããžã§ã¯ãããNewtonsoft.jsonãå»æ¢ããããšã§ãã£ãããããã®æ¹æ³ã¯æãŸããæ¹æ³ã§ã¯ãããŸããã
ãã®ãã±ãã/åé¡ã«å¯ŸåŠããããšã¯ãç§ãã¡ãçµéšããŠããåé¡ã®ä¿®æ£ãæå³ãããšæããŸããïŒ å¯ŸåŠããã®ã¯å°ãç·æ¥ã®åé¡ã®ããã§ãããé ããæ©ãã察åŠã§ããŸããïŒ
/ cc @ahsonkhan @terrajobst
ExpandoObjectïŒæ«å®æªçœ®ïŒã«å¯ŸããJsonSerializerã®ãµããŒã
ç§ã¯åå¿è
ã§ããå€ãã®å Žæã¯å®ç§ã§ã¯ãããŸããã誰ããå€æŽããããšãæè¿ããŸã
.netCore3ã¯ãµããŒããããŠããŸãã
䜿çšããŠè¿œå ïŒ
`` `CïŒ
///
/// Temp Dynamic Converter
/// byïŒ[email protected]
///
ãããªãã¯ã¯ã©ã¹DynamicJsonConverterïŒJsonConverter
{{
public override dynamic ReadïŒref Utf8JsonReader readerã
typetoConvertãšå
¥åãã
JsonSerializerOptionsãªãã·ã§ã³ïŒ
{{
if (reader.TokenType == JsonTokenType.True)
{
return true;
}
if (reader.TokenType == JsonTokenType.False)
{
return false;
}
if (reader.TokenType == JsonTokenType.Number)
{
if (reader.TryGetInt64(out long l))
{
return l;
}
return reader.GetDouble();
}
if (reader.TokenType == JsonTokenType.String)
{
if (reader.TryGetDateTime(out DateTime datetime))
{
return datetime;
}
return reader.GetString();
}
if (reader.TokenType == JsonTokenType.StartObject)
{
using JsonDocument documentV = JsonDocument.ParseValue(ref reader);
return ReadObject(documentV.RootElement);
}
// Use JsonElement as fallback.
// Newtonsoft uses JArray or JObject.
JsonDocument document = JsonDocument.ParseValue(ref reader);
return document.RootElement.Clone();
}
private object ReadObject(JsonElement jsonElement)
{
IDictionary<string, object> expandoObject = new ExpandoObject();
foreach (var obj in jsonElement.EnumerateObject())
{
var k = obj.Name;
var value = ReadValue(obj.Value);
expandoObject[k] = value;
}
return expandoObject;
}
private object? ReadValue(JsonElement jsonElement)
{
object? result = null;
switch (jsonElement.ValueKind)
{
case JsonValueKind.Object:
result = ReadObject(jsonElement);
break;
case JsonValueKind.Array:
result = ReadList(jsonElement);
break;
case JsonValueKind.String:
//TODO: Missing Datetime&Bytes Convert
result = jsonElement.GetString();
break;
case JsonValueKind.Number:
//TODO: more num type
result = 0;
if (jsonElement.TryGetInt64(out long l))
{
result = l;
}
break;
case JsonValueKind.True:
result = true;
break;
case JsonValueKind.False:
result = false;
break;
case JsonValueKind.Undefined:
case JsonValueKind.Null:
result = null;
break;
default:
throw new ArgumentOutOfRangeException();
}
return result;
}
private object? ReadList(JsonElement jsonElement)
{
IList<object?> list = new List<object?>();
foreach (var item in jsonElement.EnumerateArray())
{
list.Add(ReadValue(item));
}
return list.Count == 0 ? null : list;
}
public override void Write(Utf8JsonWriter writer,
object value,
JsonSerializerOptions options)
{
// writer.WriteStringValue(value.ToString());
}
}
## How to Use?
```C#
var serializerOptions = new JsonSerializerOptions
{
Converters = { new DynamicJsonConverter() }
};
return JsonSerializer.Deserialize<dynamic>("{OK:"200"}", serializerOptions);
@tchivs ãããªãã®è§£æ±ºçã¯ç§ã®ããã«åããã ãã ããConvertersããããã£ã¯èªã¿åãå°çšã§ããããã次ã®ãããªæäœãè¡ãå¿
èŠããããŸããã
c#
var serializerOptions = new JsonSerializerOptions();
serializerOptions.Converters.Add(new DynamicJsonConverter());
return JsonSerializer.Deserialize<dynamic>("{OK:"200"}", serializerOptions);
JsonElementã¿ã€ãã䜿çšããŠã¿ãŠãã ããã
public JsonElement MyProperty {get; set;}
@tchivs ãã³ãŒãã«ããã€ãã®å€æŽãå ããŸãããªããåçã«çæããããå°åœ±ãã¿ã€ãïŒåºæ¬ã¿ã€ãã®ããããã£ã®ãµãã»ãããæã€ïŒã䜿çšããããã«ã³ãŒããäœãçŽããŸããã ã³ãŒããïŒãµã³ãã«ã³ã³ãœãŒã«ãããžã§ã¯ãã§ïŒããã«æçš¿ããŸããïŒ EDennis.DynamicDeserialization ã
ãã®ã¢ãããŒãã¯ãããè€éãªãªããžã§ã¯ãã䜿çšããŠãããŸããŸãªã·ããªãªã§ãã¹ãããŸãïŒããšãã°ãæ¢åã®å®å šã«åæå®ãããEFã³ã¢ãšã³ãã£ãã£ã«ããããé©çšããããã«äœ¿çšãããåçãªããžã§ã¯ãã®éã·ãªã¢ã«åããã¹ãã±ãŒã¹ã®jsonãªããžã§ã¯ããšé åã®éã·ãªã¢ã«åïŒã ããã圹ç«ã€ãšæãããå ŽåããŸãã¯åé¡ãããå Žåã¯ãç¥ãããã ããã
ã³ãã¥ããã£ã®åé¿çãããããšãã ãã€ã¯ããœããããã®æ©èœãé©åãªæéæ ã§æäŸã§ããªãã®ã¯é©ãã¹ãããšã§ãã ããçš®ã®åçãªããžã§ã¯ããªãã§GraphQLå¿çãæäœãããšãå€ãã®åé·ã§éãã³ãŒãã«ãªããŸãã ãŸãã¯ãæ·±ããã¹ããããããããã£ã®ååšã確èªããã ãã§ãããŸããŸããã
ã³ã¡ã³ãã®ã¹ã¬ãããèªã¿ãŸããããã»ãšãã©ãéã·ãªã¢ã«åã«çŠç¹ãåœãŠãŠããŸããåçãªããžã§ã¯ãã®ã·ãªã¢ã«åãæããã«ã倱æããããšããåé¡ã«çŽé¢ããŠããŸãã ç§ã®ã·ããªãªãåçŸããããã«ã次ã®æå°éã®åçŸãæãã€ããŸããã
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text.Json;
namespace SampleConsoleApp
{
class Program
{
static void Main(string[] args)
{
dynamic d = new CustomDynamicObject();
d.AProperty = 10;
var s = JsonSerializer.Serialize(d);
Console.WriteLine(s);
Console.Read();
}
}
class CustomDynamicObject : DynamicObject
{
private readonly IDictionary<string, object> properties = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result) => properties.TryGetValue(binder.Name, out result);
public override bool TrySetMember(SetMemberBinder binder, object value)
{
properties[binder.Name] = value;
return true;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
foreach (var item in properties.Keys)
{
yield return item;
}
}
}
}
s
å®è¡ãããš{}
ã«ãªããããã·ãªã¢ã«åã¯å€±æããŸãããã空ã®jsonãªããžã§ã¯ããçæãããŸãã
ããã¯æ£ããåé¡ã§ããïŒ ãŸãã¯ãå¥ã®ãã®ãã¬ã€ãº/ãã©ããŒããå¿ èŠããããŸããïŒ
ããã¯æ£ããåé¡ã§ããïŒ ãŸãã¯ãå¥ã®ãã®ãã¬ã€ãº/ãã©ããŒããå¿ èŠããããŸããïŒ
ããã¯æ£ããåé¡ã§ãã åãæ©èœã®2ã€ã®ååã®ããã«1ã€ãéãå¿ èŠã¯ãããŸããã ãã®åé¡ã¯ãexpandoãªããžã§ã¯ãã®ãµããŒããè¿œå ããããšã«é¢ãããã®ã§ãïŒã€ãŸããäž¡åŽã§ã·ãªã¢ã«åãšéã·ãªã¢ã«åãè¡ããŸãïŒã
ç§ã¯ä»æ¥ãã®åé¡ã«ééããŸãã-ãããåŠåãããJsonDocument
äŸåããŠããªããã°ã JsonElement
ã¯ããŸããããšèšãããã£ãã®ã§ãã ãã®åé¡ãåé¿ããæ¹æ³ã®1ã€ã¯ã JsonDocument
ãã¹ãã©ã¯ã¿ãå®è£
ããŠããã¹ãŠã®JsonElement
ãªããžã§ã¯ããåéãããããç Žæ£ãåŸã§å»¶æã§ããããã«ããããšã§ãã
åçãªããžã§ã¯ããå¿
èŠã§ããã ãã ãããŸã å®è£
ãããŠããŸããã ç§ã®è§£æ±ºçã¯èŸæžã䜿ãããšã§ããã
JsonSerializer.Deserialize<Dictionary<string, string>>(response)
ãããŠãå¿
èŠãªããŒãæ¢ããŸã:)
ç§èªèº«ã®æ£æ°ã®ããã«-åé¡ã®ç¯å²ã¯5.0ãç¹ã«ExpandoObjectã®ãµããŒãã§ããããããšãåçãªããžã§ã¯ãã«éã·ãªã¢ã«åããæ©èœã§ããïŒ ããã§ã®äŒè©±ã¯ãã¹ãŠåé¡ã®ã¿ã€ãã«ãšäžèŽããŠããªãããã§ãç§ã¯ééããªãåŸè
ãå¿
èŠã§ãã ç§ã®å Žåããã¹ãããããã€ãããã¯ãå
·äœçã«ã¯List<Dictionary<string, dynamic>>
éã·ãªã¢ã«åããŸãã ä»ã®ãšããNewtonsoftã«åãæ¿ããŸãã:(
@tchivsã®åœ¹ç«ã€ã³ãŒãã®cïŒ8æ§æã·ã¥ã¬ãŒã¢ãããå ±æãããã£ãã ãã§ã:)
/// <summary>
/// Temp Dynamic Converter with c# 8
/// by:[email protected]
/// </summary>
public class DynamicJsonConverter : JsonConverter<dynamic>
{
public override dynamic Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> reader.TokenType switch
{
JsonTokenType.True => true,
JsonTokenType.False => false,
JsonTokenType.Number => reader.TryGetInt64(out long l) ? 1 : reader.GetDouble(),
JsonTokenType.String => reader.TryGetDateTime(out DateTime datetime) ? datetime.ToString() : reader.GetString(),
JsonTokenType.StartObject => ReadObject(JsonDocument.ParseValue(ref reader).RootElement),
// Use JsonElement as fallback.
_ =>JsonDocument.ParseValue(ref reader).RootElement.Clone()
};
private object ReadObject(JsonElement jsonElement)
{
IDictionary<string, object> expandoObject = new ExpandoObject();
foreach (var obj in jsonElement.EnumerateObject())
{
var k = obj.Name;
var value = ReadValue(obj.Value);
expandoObject[k] = value;
}
return expandoObject;
}
private object? ReadValue(JsonElement jsonElement)
=>
jsonElement.ValueKind switch
{
JsonValueKind.Object => ReadObject(jsonElement),
JsonValueKind.Array => ReadList(jsonElement),
JsonValueKind.String => jsonElement.GetString(),
JsonValueKind.Number => jsonElement.TryGetInt64(out long l) ? 1 :0,
JsonValueKind.True => true,
JsonValueKind.False =>false,
JsonValueKind.Undefined => null,
JsonValueKind.Null => null,
_ => throw new ArgumentOutOfRangeException()
};
private object? ReadList(JsonElement jsonElement)
{
var list = new List<object?>();
jsonElement.EnumerateArray().ToList().ForEach(j => list.Add(ReadValue(j)));
return list.Count == 0 ? null : list;
}
public override void Write(Utf8JsonWriter writer,
object value,
JsonSerializerOptions options)
{
// writer.WriteStringValue(value.ToString());
}
}
@ rs38ããã®ã³ãŒãã«æè¬ããŸãããŸãã«ç§ãå¿ èŠãšããŠãããã®ã§ããã éåžžã«åŸ®åŠã ãéèŠãªå€æŽãå¿ èŠã§ããããšãææãããã£ãã ãæ°å€ãã¿ã€ãã解æãã2è¡ã¯ãå§çž®ããŒãžã§ã³ã§ã¯æ£ãããããŸããã
JsonTokenType.Number => reader.TryGetInt64(out long l) ? 1 : reader.GetDouble(),
ããå¿ èŠããããŸã
JsonTokenType.Number => reader.TryGetInt64(out long l) ? l : reader.GetDouble(),
JsonValueKind.Number => jsonElement.TryGetInt64(out long l) ? 1 :0,
ããå¿ èŠããããŸã
JsonValueKind.Number => jsonElement.TryGetInt64(out long l) ? l :0,
@layomiaããã¯æ·±å»ã§ã¯ãããŸããã ãµããŒãã¯ãã£ãšåã«è¡ãããã¹ãã§ããïŒå®éãç§ã®æèŠã§ã¯ãSystem.Text.Jsonã¯ãããªãã§èµ·åãããã¹ãã§ã¯ãããŸããã§ããïŒïŒ ãããŠãæéããããŸããïŒ
ç§ã®ã·ããªãªã¯CosmosDBã«é¢ãããã®ã§ãã ãã®JsonSerializerã䜿çšããæ°ãã.NETSDKã䜿çšããŠã¯ãšãªãå®è¡ããŠããŸããããã¯ã¹ããŒãã¬ã¹ããŒã¿ããŒã¹ã§ãããããå®è¡ããå¿
èŠã®ããããŒã¿ããŒã¹ããŒã¿ã®æ圱ããšã«ã¯ã©ã¹ãäœæããããããŸããïŒããŸããŸãªã¯ãšãªãå€æ°ãããŸãïŒ ã
åçãªããžã§ã¯ãã®ãªã¹ããšããŠã¯ãšãªã®çµæãå¿
èŠã§ãã
@ SocVi100ããã«ã€ããŠMicrosoftã«æåŸ ããªãã§ãã ããã Newtonsoftã®Json.netã䜿ãç¶ããããšããå§ãããŸãã @layomiaã¯ãè¿ãå°æ¥ã®çµ±åãžã®ãã¹ãŠã®æåŸ ã
è²¢ç®ããŠã¿ãŸãããïŒ ãããå®è£ ããŠPRã«å ¥ããŠãã ããïŒ
https://github.com/dotnet/runtime/blob/master/docs/coding-guidelines/adding-api-guidelines.md
https://github.com/dotnet/runtime/blob/master/docs/area-owners.md ïŒãªãŒãïŒ
@ericstj |ãææè
ïŒ @layomia @steveharter @jozkeeïŒ
è²¢ç®ããŠã¿ãŸãããïŒ ãããå®è£ ããŠPRã«å ¥ããŠãã ããïŒ
ç§ãããåºæ¥ãã°ãããã©ã
ç§ã®ã·ããªãªã¯CosmosDBã«é¢ãããã®ã§ãã ãã®JsonSerializerã䜿çšããæ°ãã.NETSDKã䜿çšããŠã¯ãšãªãå®è¡ããŠããŸããããã¯ã¹ããŒãã¬ã¹ããŒã¿ããŒã¹ã§ãããããå®è¡ããå¿ èŠã®ããããŒã¿ããŒã¹ããŒã¿ã®æ圱ããšã«ã¯ã©ã¹ãäœæããããããŸããïŒããŸããŸãªã¯ãšãªãå€æ°ãããŸãïŒ ã
åçãªããžã§ã¯ãã®ãªã¹ããšããŠã¯ãšãªã®çµæãå¿ èŠã§ãã
CosmosClientBuilder.WithCustomSerializerã䜿çšããŠãå¥ã®
次ã«äŸã瀺ããŸããCosmosJsonNetSerializer
ãã®æ©èœã5.0ã«é©åãããããšãã§ããŸããã§ããã 5.0ã®æ©èœã®æ®ãã®éšåãšäžç·ã«åªå é äœãä»ããå¿ èŠããããŸããããããã¯é©åããŸããã§ããã FWIWããã¯ã«ããã©ã€ã³ã«éåžžã«è¿ãã£ããããåããé ããªããŸããã
@layomiaã¯ãè¿ãå°æ¥ã®çµ±åãžã®ãã¹ãŠã®æåŸ ã
@RobbyDeLaetãã®è°è«ã建èšçã«ä¿ã€ããšãè©Šã¿ãããšãã§ããŸããïŒ ç§ãã¡ã¯ãèšèšååãç¶æããªãããæãèŠæ±ããã顧客ã®æ©èœã«å¯Ÿå¿ããããã«æåãå°œãããŠããŸãã Newtonsoft.Jsonãšã®æ©èœã®åçæ§ã«é¢ããŠããããç§ãã¡ãèšããªããã°ãªã
System.Text.Jsonã¯ãäž»ã«ããã©ãŒãã³ã¹ãã»ãã¥ãªãã£ãããã³æšæºãžã®æºæ ã«éç¹ã眮ããŠããŸãã äžéšã®ã·ããªãªã§ã¯ãSystem.Text.Jsonã«çµã¿èŸŒã¿ã®æ©èœã¯ãããŸããããæšå¥šãããåé¿çããããŸãã ã¢ããªã±ãŒã·ã§ã³ãäžè¶³ããŠããæ©èœã«äŸåããŠããå Žåã¯ãåé¡ãæåºããŠãã·ããªãªã®ãµããŒããè¿œå ã§ãããã©ããã確èªããããšãæ€èšããŠãã ããã
Newtonsoft.JSONã眮ãæããããšã¯ç®æããŠããŸããã ãããããªãã®ããã«åããªãã°ãããã䜿ãç¶ããŠãã ããã System.Text.Jsonãå¯èœãªéãæçšãªãã®ã«ããããã«æåãå°œãããããã©ãŒãã³ã¹ãã»ãã¥ãªãã£ãæšæºãžã®æºæ ãããã³éå±€åã§éæããå©çãç¶æããŸãã æéããããŠãã§ããã ãå€ãã®äººã ã®ããã«ãããæ©èœããããã«ããããšæã£ãŠããŸãã ç§ã¯ããã§é¢å¿ãèããŠãããä»åŸãããã«çŠç¹ãåœãŠãããšã確èªããŸãã
ããªãã®ææ¡ãããããšãã Newtonsoftã·ãªã¢ã©ã€ã¶ãŒãéã·ãªã¢ã«åã«ã®ã¿äœ¿çšããŠãããããéäžã§çµãããŸããããããã§ããã¹ãããå¿
èŠããããŸãã CosmosDBã®ããã©ã«ãã®ã·ãªã¢ã©ã€ã¶ãŒã§ExpandoObjectã®ãµããŒããååŸããŠãå€ãã·ãªã¢ã©ã€ã¶ãŒãåé€ã§ããããã«ãªããŸã§ãããã»ã©é·ãã¯ç¶ããªãããšãé¡ã£ãŠããŸãã
@RobbyDeLaet ãã³ã¡ã³ãããããšã
åé¡ã¯åžžã«åãã§ãïŒããŒã±ãã£ã³ã°ãå€ããã=æåŸ
ãå€ããã
ãã®æ©èœãå¿ èŠãªãŠãŒã¶ãŒãæ¯æŽããã«ã¯ãäžèšã®ã³ãŒããµã³ãã«ãåç §ããŠãããã¯ã解é€ããŠãã ããã
ExpandoObject
ã䜿çšããã³ã¬ã¯ã·ã§ã³ã«ã¯List<object>
ã䜿çšããŸãïŒExpandoObject
代ããã«ãªããžã§ã¯ãã«IL Emitã䜿çšããŸãïŒãã®æ©èœã®èŠä»¶ãæ¯æŽããããã«ãæ°ããã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã®ãµã³ãã«ãæäŸããæºåãã§ãããããã«ãªã³ã¯ããŸãã ãã®åŸããã®ãµã³ãã«ãNewtonsoftã®åé¿çã»ã¯ã·ã§ã³ã«è¿œå ããŸãã cc @tdykstra
ãŸã 説æãããŠããªã詳现ã®1ã€ã¯ã dynamic
ããµããŒãããã«ã¯ãéåžžã«å€§ããªSystem.Linq.Expressions.dll
ã¢ã»ã³ããªãžã®åç
§ãå¿
èŠã§ããããšã§ãã ãã®è€éãã¯ãå°æ¥ãæ°ããã¢ã»ã³ããªïŒ System.Text.Json.Converters.dll
ïŒã«åçã³ã³ããŒã¿ãŒãè¿œå ããŠããããã€ãµã€ãºãæ°ã«ãã人ïŒèªå·±å®çµåã¢ããªãBlazorãªã©ïŒã®ãã€ã»ãã¥ã»ãã¬ã€ãååŸããããšãæå³ããå¯èœæ§ããããŸãã¯ã©ã€ã¢ã³ãã¢ããªïŒã
ç§èªèº«ã®æ£æ°ã®ããã«-åé¡ã®ç¯å²ã¯5.0ãç¹ã«ExpandoObjectã®ãµããŒãã§ããããããšãåçãªããžã§ã¯ãã«éã·ãªã¢ã«åããæ©èœã§ããïŒ ããã§ã®äŒè©±ã¯ãã¹ãŠåé¡ã®ã¿ã€ãã«ãšäžèŽããŠããªãããã§ãç§ã¯ééããªãåŸè ãå¿ èŠã§ãã ç§ã®å Žåããã¹ãããããã€ãããã¯ãå ·äœçã«ã¯
List<Dictionary<string, dynamic>>
éã·ãªã¢ã«åããŸãã ä»ã®ãšããNewtonsoftã«åãæ¿ããŸãã:(
çŸåšããã¹ãããããªããžã§ã¯ããéã·ãªã¢ã«åããããã«å®è£ ããå€ãé¢æ°ããã¹ãããŠããããã®ãããã¯ã§ãvalueKindãã«èšèŒãããŠããã®ãšåãåé¡ãçºçããŠããŸãã
æ°ããneetonsoft.jsonããã±ãŒãžã䜿çšããŠãããä¿®æ£ããæ¹æ³ã¯ãããŸãããïŒ äžèšã®ã³ãŒãã¯ã«ãŒãã¬ãã«ã®ãªããžã§ã¯ãã§ã¯æ©èœããŸãããããã¹ãããããªããžã§ã¯ãã§ã¯æ©èœããªãã£ãããã§ãã
@ericstjç³ãèš³ãããŸããããç§ã®åå¿ã¯ããããå°ãåŠå®çã§å³ãããã®ã§ãããã åªå¢ã«ãªããŸãã ããããå°ãªããšãããã§è°è«ãå§ãŸããŸããã ãè¿ä¿¡ããã ãããããšãããããŸãããã®ãªã¯ãšã¹ãã®ã¹ããŒã¿ã¹ã«ã€ããŠãå°ãªããšãæ確ãªã¡ãã»ãŒãžãå±ããŸããã
ç§èªèº«ã®æ£æ°ã®ããã«-5.0ãç¹ã«ExpandoObjectã®ãµããŒããŸãã¯åçãªããžã§ã¯ãã«ãã·ãªã¢ã©ã€ãºããæ©èœã®å¯Ÿè±¡ãšãªãåé¡ã§ã
å¿ èŠãªã»ãã³ãã£ã¯ã¹ã¯åçã¿ã€ãã§ãããšæ³å®ããŠãããããéã·ãªã¢ã«åããåŸããã¹ãŠã®ããããã£ïŒãã¹ãããããã®ãå«ãïŒã«ã¬ã€ãããŠã³ãã§ã¢ã¯ã»ã¹ã§ããŸãã
dynamic obj = JsonSerializer.Deserialize<dynamic>(json);
string s = obj.MyChildProperty.MyStringList[2];
ãããŠãå¿
èŠãªã»ãã³ãã£ã¯ã¹ãæ瀺çã«ExpandoObject
ãµããŒããããšæããŸãã
ExpandoObject expando = JsonSerializer.Deserialize<ExpandoObject>(json);
dynamic obj = expando;
string s = obj.MyChildProperty.MyStringList[2];
ã ããç§ã®ã¹ã³ãŒãã®ç解ïŒ
Deserialize<dynamic>(json)
ã¯ãããªããã£ããã³ã¬ã¯ã·ã§ã³ããŸãã¯ãªããžã§ã¯ãã®ãããããè¿ããŸãã ããã§ã®ãªããžã§ã¯ãã¯ããããExpandoObject
ããå®è£
ã«å¿ããŠIDynamicMetaObjectProvider
ãŸãã¯JITedã¿ã€ãã«ãªãå¯èœæ§ããããŸãã ããã¯ãåžžã«JsonElement
è¿ãä»æ¥ãšã¯ç°ãªããŸããDeserialize<ExpandoObject>(json)
ïŒ IDynamicMetaObjectProvider
ãå®è£
ïŒã¯é©åãªExpandoObject
ãäœæããå¿
èŠãããããããdynamic
ã§äœ¿çšã§ããŸãã ããã¯ãã«ãŒãããããã£ã®expando-propertiesãšããã¹ãããããã¹ãŠã®ããããã£ã®JsonElement
ã€ã³ã¹ã¿ã³ã¹ã®ã¿ãäœæããä»æ¥ãšã¯ç°ãªããŸããSerialize<ExpandoObect>()
ã¯æåŸ
ã©ããã«æ©èœããŸãSerialize<IDynamicMetaObjectProvider
ïŒïŒ>ã¯ã ExpandoObject
ã䜿çšãããªãã·ããªãªããããã©ããã«å¿ããŠãå®è£
ãããå Žåãšãããªãå ŽåããããŸãã3.0-5.0ã®ã»ãã³ãã£ã¯ã¹ïŒ
ExpandoObject
ã¯IDictionary<string, object>
ãå®è£
ããSTJã¯ããªããã£ããã³ã¬ã¯ã·ã§ã³ããªããžã§ã¯ãã®ãããã§ãã£ãŠããåobject
å€ãæ£ããã·ãªã¢ã«åããããã ExpandoObject
ã·ãªã¢ã«åã¯æ©èœããŸããExpandoObject
çš®é¡ã®äœåã«éã·ãªã¢ã«åããŸãããã«ãŒãããããã£ã®ã¿ããé©åãªãexpando-propertiesã§ãã ãã¹ããããããããã£ã¯JsonElement
ãªããããããã°ã©ãã³ã°ã¢ãã«ã«äžè²«æ§ããªããããã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã䜿çšããªãéãã ExpandoObject
éã·ãªã¢ã«å3.0ã5.0ã®ãªãã·ã§ã³ïŒ
ExpandoObject
ããã³\ãŸãã¯object
ã«ã¹ã¿ã ã³ã³ããŒã¿ãŒãäœæããŸãã 6.0ã®æ©èœã«çæ³çã«ãããã³ã°ãããæ°ãããµã³ãã«ãžã®ãªã³ã¯ãããã«æäŸããŸããExpandoObject
ïŒãŸãã¯dynamic
ã¿ã€ãã¯ã«åºã¥ããŠããå Žåã ExpandoObject
ïŒã ExpandoObject
éã·ãªã¢ã«åã«ã¯ãä»æ¥ã®STJã§ã®äžæŽåã®åé¡ããããããéã·ãªã¢ã«åããå Žåã¯ExpandoObject
ã¯ãå§ãããŸãããJsonElement
䜿çšããŸãã JsonElement
ã¯ãJSONãã©ã®ã¿ã€ãã«ãããããããããæšæž¬ãããããšããªããããGetStringïŒïŒãGetInt32ïŒïŒãªã©ãåŒã³åºããŠæ瀺çã«ããå¿
èŠããããŸãããŸããå®è£
ã«ãã£ãŠã¯ãã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã®å®è£
ã¯ãéã·ãªã¢ã«åäžã«JSONããããCLRã¿ã€ããããã®ã«ã€ããŠäœããã®ãæšæž¬ããããããšãæå³ããå¯èœæ§ããããŸãã ããšãã°ãJSONæååã¯DateTime
ãŸãã¯string
ããããã«ããããããJSONçªå·ã¯double
ãŸãã¯long
ã«ããããããŸãã JSONé
åã¿ã€ãã決å®ããå¿
èŠããããŸãã ããã粟æ»ããNewtonsoftã»ãã³ãã£ã¯ã¹ãšæ¯èŒããå¿
èŠããããŸãã ããã¯ãããããã£ãã¿ã€ãobject
ïŒçŸåšã¯JsonElement
ïŒã®å Žåã«è¿ãããã¿ã€ãã«ãäžèŽããå¿
èŠããããŸãã
3.0ã5.0ã®STJã»ãã³ãã£ã¯ã¹ã®äŸã次ã«ç€ºããŸãã
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
namespace ConsoleApp
{
class Program
{
const string ExpectedJson = "{\"A\":\"A\",\"B\":[1,2],\"C\":42,\"D\":\"2020-01-01T00:00:00\",\"E\":{\"A_Child\":\"A_Child\"}}";
static void Main(string[] args)
{
DateTime dateTime = new DateTime(2020, 1, 1);
dynamic myDynamicChild = new ExpandoObject();
myDynamicChild.A_Child = "A_Child";
dynamic myDynamic = new ExpandoObject();
myDynamic.A = "A";
myDynamic.B = new List<int>() { 1, 2 };
myDynamic.C = 42;
myDynamic.D = dateTime;
myDynamic.E = myDynamicChild;
// Verify we can call late-bound property.
int c = myDynamic.C;
Debug.Assert(c == 42);
// STJ can serialize with ExpandoObject since it implements IDictionary<string, object>.
string json = JsonSerializer.Serialize<ExpandoObject>(myDynamic);
Debug.Assert(json == ExpectedJson);
// Using 'dynamic' against backing ExpandoObject works.
json = JsonSerializer.Serialize<dynamic>(myDynamic);
Debug.Assert(json == ExpectedJson);
// Deserialize with <dynamic>, <object> and <JsonElement>.
// For 5.0, using one of these is recommended over ExpandoObject because the programming model will be
// consistent for the root type and all nested types.
// Using <JsonElement> makes it clear and non-abiguous.
// Using <object> by default uses 'JsonElement', but can be overridden by a custom converter.
// Using <dynamic> uses 'object' which uses 'JsonElement'.
{
dynamic d = JsonSerializer.Deserialize<dynamic>(json);
VerifyJsonElement(d);
try
{
// We will get an exception here if we try to access a dynamic property since 'object' is deserialized
// as a JsonElement and not an ExpandoObject.
c = d.C;
Debug.Fail("Should have thrown Exception!");
}
catch (Exception ex)
{
Debug.Assert(ex.Message == "'System.Text.Json.JsonElement' does not contain a definition for 'C'");
}
// Serializing with <object> creates a JsonElement by default (can be changed by a custom converter).
object o = JsonSerializer.Deserialize<object>(json);
VerifyJsonElement((JsonElement)o);
// Serialize with explicit <JsonElement>.
JsonElement e = JsonSerializer.Deserialize<JsonElement>(json);
VerifyJsonElement(e);
}
// Deserialize with ExpandoObject. This creates an ExpandoObject with the root Type having Expando-properties
// but the value of those properties will be JsonElement. All other nested properties\objects\collections will
// also be JsonElement. Due to the inconsistency of having only root-level Expando-properties (such as A_Child),
// deserializing as ExpandoObject is not recommended (unless a ExpandoObject custom converter is used).
{
// When STJ deserializes, it creates ExpandoObjects via IDictionary<string, object> where 'object' is JsonElement.
ExpandoObject expando = JsonSerializer.Deserialize<ExpandoObject>(json);
Debug.Assert(((IDictionary<string, object>)expando).Keys.Count == 5);
myDynamic = expando;
JsonElement jsonElement = myDynamic.A;
Debug.Assert(jsonElement.GetString() == "A");
jsonElement = myDynamic.B;
Debug.Assert(jsonElement.EnumerateArray().Count() == 2);
jsonElement = myDynamic.C;
Debug.Assert(jsonElement.GetInt32() == 42);
jsonElement = myDynamic.D;
Debug.Assert(jsonElement.GetDateTime() == dateTime);
jsonElement = myDynamic.E;
// Here we have an inconsistency. Nested object property must use JsonElement (not a dynamic property).
Debug.Assert(jsonElement.GetProperty("A_Child").GetString() == "A_Child");
// Re-serialize works as expected.
json = JsonSerializer.Serialize<ExpandoObject>(myDynamic);
Debug.Assert(json == ExpectedJson);
// Re-serialize works as expected; dynamic works here since backed by ExpandoObject in this example.
json = JsonSerializer.Serialize<dynamic>(myDynamic);
Debug.Assert(json == ExpectedJson);
}
void VerifyJsonElement(JsonElement elem)
{
// Verify JsonElement
Debug.Assert(elem.GetProperty("A").GetString() == "A");
Debug.Assert(elem.GetProperty("B").EnumerateArray().Count() == 2);
Debug.Assert(elem.GetProperty("C").GetInt32() == 42);
Debug.Assert(elem.GetProperty("D").GetDateTime() == dateTime);
Debug.Assert(elem.GetProperty("E").GetProperty("A_Child").GetString() == "A_Child");
// Re-serialize
json = JsonSerializer.Serialize<dynamic>(elem);
Debug.Assert(json == ExpectedJson);
json = JsonSerializer.Serialize<JsonElement>(elem);
Debug.Assert(json == ExpectedJson);
}
}
}
}
@ rs38 @ ryan -hollister-q2ãææããããšã«åºã¥ããŠãã³ãŒãã¹ãããããä¿®æ£ã§ããŸããïŒ
çŽæã©ãããåçãªå®è£ ãµã³ãã«ãæäŸããPRã¯https://github.com/dotnet/runtime/pull/42097ã«ãããŸãã
@ rs38 @ ryan -hollister-q2ãææããããšã«åºã¥ããŠãã³ãŒãã¹ãããããä¿®æ£ã§ããŸããïŒ
ããã¯ç§ã®ã³ãŒãã§ã¯ãªãããã®ã¹ã¬ããã®ååã§@tchivsããã®ã¹ãããããå ±æããã ãã§ãã
æãåèã«ãªãã³ã¡ã³ã
ããã®ãŠãŒã¹ã±ãŒã¹ããããŸããHttpClientã䜿çšããŠRESTAPIãåŒã³åºããå¿çããåäžã®ããããã£ãååŸãããã ãã§ãã å¿çã解æããããã ãã«å°çšã®ã¯ã©ã¹ãäœæããããããŸãã... JSON.NETã䜿çšãããšããåçãã䜿çšããŠãéžæããããããã£ã«ã¢ã¯ã»ã¹ã§ããŸãã