Skip to content

Instantly share code, notes, and snippets.

@neuecc
Last active May 17, 2018 13:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neuecc/161fe0ae68cbb3ea1f2ccb6db84d8504 to your computer and use it in GitHub Desktop.
Save neuecc/161fe0ae68cbb3ea1f2ccb6db84d8504 to your computer and use it in GitHub Desktop.
// AutomataDictionaryを使う&むしろType無視してIValueだけで済ましてしまうパターン(こら
// reader.ReadObjectSegment/ReadArraySegmentがあって、小ブロックを取得できるようにすれば解決しそう(追加します
public class Container
{
public string Type { get; set; }
public IValue Value { get; set; }
}
[JsonFormatter(typeof(InterfaceFormatter))]
public interface IValue
{
}
public class InterfaceFormatter : IJsonFormatter<IValue>
{
static readonly AutomataDictionary automata = new AutomataDictionary();
static InterfaceFormatter()
{
automata.Add("Foo", 0);
automata.Add("Hoge", 1);
}
public IValue Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
{
if (reader.ReadIsNull()) return null;
var count = 0;
IValue result = null;
while (reader.ReadIsInObject(ref count))
{
var propName = reader.ReadPropertyNameSegmentRaw();
var i = -1;
automata.TryGetValue(propName, out i);
switch (i)
{
case 0:
result = new ValueTypeA { Foo = reader.ReadInt32() };
break;
case 1:
result = new ValueTypeB { Hoge = reader.ReadString() };
break;
default:
reader.ReadNextBlock();
break;
}
}
return result;
}
public void Serialize(ref JsonWriter writer, IValue value, IJsonFormatterResolver formatterResolver)
{
throw new NotImplementedException();
}
}
public class ValueTypeA : IValue
{
public int Foo { get; set; }
}
public class ValueTypeB : IValue
{
public string Hoge { get; set; }
}
class Program
{
static void Main(string[] args)
{
var json = @"
{
""Type"": ""TypeA"",
""Value"": {
""Foo"": 10
}
}
";
JsonSerializer.Deserialize<Container>(json).Dump();
json = @"
{
""Value"": {
""Hoge"": ""mogemoge""
},
""Type"": ""TypeB""
}
";
JsonSerializer.Deserialize<Container>(json).Dump();
var container = JsonSerializer.Deserialize<Container>(json);
if (container.Type == "TypeA")
{
var value = (ValueTypeA)container.Value;
value.Foo.Dump();
}
else if (container.Type == "TypeB")
{
var value = (ValueTypeB)container.Value;
value.Hoge.Dump();
}
}
}
// dynamic使えばJSON.NET likeですよパターン
[JsonFormatter(typeof(ContainerFormatter))]
public class Container
{
public string Type { get; set; }
public IValue Value { get; set; }
public class ContainerFormatter : IJsonFormatter<Container>
{
public Container Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
{
if (reader.ReadIsNull()) return null;
var obj = formatterResolver.GetFormatterWithVerify<dynamic>().Deserialize(ref reader, formatterResolver);
var type = obj["Type"] as string;
var value = (type == "TypeA") ? new ValueTypeA { Foo = (int)obj["Value"]["Foo"] }
: (type == "TypeB") ? new ValueTypeB { Hoge = (string)obj["Value"]["Hoge"] }
: (IValue)null;
return new Container()
{
Type = type,
Value = value
};
}
public void Serialize(ref JsonWriter writer, Container value, IJsonFormatterResolver formatterResolver)
{
throw new NotImplementedException();
}
}
}
public interface IValue
{
}
public class ValueTypeA : IValue
{
public int Foo { get; set; }
}
public class ValueTypeB : IValue
{
public string Hoge { get; set; }
}
class Program
{
static void Main(string[] args)
{
var json = @"
{
""Type"": ""TypeA"",
""Value"": {
""Foo"": 10
}
}
";
JsonSerializer.Deserialize<Container>(json).Dump();
json = @"
{
""Value"": {
""Hoge"": ""mogemoge""
},
""Type"": ""TypeB""
}
";
JsonSerializer.Deserialize<Container>(json).Dump();
var container = JsonSerializer.Deserialize<Container>(json);
if (container.Type == "TypeA")
{
var value = (ValueTypeA)container.Value;
value.Foo.Dump();
}
else if (container.Type == "TypeB")
{
var value = (ValueTypeB)container.Value;
value.Hoge.Dump();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment