答えて
あなたがしようとしていることは可能ですが、些細なことではなく、JSON.NETの組み込み属性のみでは実行できません。カスタム属性とカスタム契約リゾルバが必要です。
ここで私が思いついた解決策です:
は、このカスタム属性を宣言します。
[AttributeUsage(AttributeTargets.Property)]
class JsonPropertyGenericTypeNameAttribute : Attribute
{
public int TypeParameterPosition { get; }
public JsonPropertyGenericTypeNameAttribute(int position)
{
TypeParameterPosition = position;
}
}
は
public class Response<T> : Response
{
[JsonPropertyGenericTypeName(0)]
public T Data { get; set; }
}
(0 Response<T>
にT
の位置であり、あなたのData
プロパティに適用しますジェネリック型パラメータ)
JsonPropertyGenericTypeName
属性を探します、次の契約リゾルバを宣言し、型引数の実際の名前を取得:
var settings = new JsonSerializerSettings { ContractResolver = new GenericTypeNameContractResolver() };
string json = JsonConvert.SerializeObject(response, settings);
これは与える:あなたのシリアル化の設定で
class GenericTypeNameContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var prop = base.CreateProperty(member, memberSerialization);
var attr = member.GetCustomAttribute<JsonPropertyGenericTypeNameAttribute>();
if (attr != null)
{
var type = member.DeclaringType;
if (!type.IsGenericType)
throw new InvalidOperationException($"{type} is not a generic type");
if (type.IsGenericTypeDefinition)
throw new InvalidOperationException($"{type} is a generic type definition, it must be a constructed generic type");
var typeArgs = type.GetGenericArguments();
if (attr.TypeParameterPosition >= typeArgs.Length)
throw new ArgumentException($"Can't get type argument at position {attr.TypeParameterPosition}; {type} has only {typeArgs.Length} type arguments");
prop.PropertyName = typeArgs[attr.TypeParameterPosition].Name;
}
return prop;
}
}
シリアル化このリゾルバとしResponse<Foo>
の出力
{
"Foo": {
"Id": 0,
"Name": null
}
}
ここでは、それを実現するための簡単な方法があります。あなたがする必要があるのは、このように、応答はjオブジェクトを拡張することです。
public class Response<T>: Newtonsoft.Json.Linq.JObject
{
private static string TypeName = (typeof(T)).Name;
private T _data;
public T Data {
get { return _data; }
set {
_data = value;
this[TypeName] = Newtonsoft.Json.Linq.JToken.FromObject(_data);
}
}
}
あなたが行う場合は、その期待どおりに動作します以下:
static void Main(string[] args)
{
var p1 = new Response<Int32>();
p1.Data = 5;
var p2 = new Response<string>();
p2.Data = "Message";
Console.Out.WriteLine("First: " + JsonConvert.SerializeObject(p1));
Console.Out.WriteLine("Second: " + JsonConvert.SerializeObject(p2));
}
出力:
First: {"Int32":5}
Second: {"String":"Message"}
Response<T>
がJObjectを拡張することができない場合は、Responseを拡張するために本当に必要なので、Response自体にJObjectを拡張させてから、Response<T>
にResponseをb efore。まったく同じように動作するはずです。
これは創造的な解決策ですが、「レスポンスをJObjectに拡張するだけです」というメッセージは非常に大きなものです。 –
レスポンスを拡張できない場合は、コンポジションを使用して同様のコンテナ
@Thomas Levesque:OK。したがって、既存のResponseクラスを拡張する必要があるため、Response<T>
でJObjectを拡張できないとしましょう。ここでは、同じソリューションを実装することができ、別の方法があります:
public class Payload<T> : Newtonsoft.Json.Linq.JObject {
private static string TypeName = (typeof(T)).Name;
private T _data;
public T Data {
get { return _data; }
set {
_data = value;
this[TypeName] = Newtonsoft.Json.Linq.JToken.FromObject(_data);
}
}
}
//Response is a pre-existing class...
public class Response<T>: Response {
private Payload<T> Value;
public Response(T arg) {
Value = new Payload<T>() { Data = arg };
}
public static implicit operator JObject(Response<T> arg) {
return arg.Value;
}
public string Serialize() {
return Value.ToString();
}
}
だから今、クラスをシリアル化するために、次のオプションがあります。
static void Main(string[] args) {
var p1 = new Response<Int32>(5);
var p2 = new Response<string>("Message");
JObject p3 = new Response<double>(0.0);
var p4 = (JObject) new Response<DateTime>(DateTime.Now);
Console.Out.WriteLine(p1.Serialize());
Console.Out.WriteLine(p2.Serialize());
Console.Out.WriteLine(JsonConvert.SerializeObject(p3));
Console.Out.WriteLine(JsonConvert.SerializeObject(p4));
}
出力は次のようになります:
{"Int32":5}
{"String":"Message"}
{"Double":0.0}
{"DateTime":"2016-08-25T00:18:31.4882199-04:00"}
- 1. Typescript。これは必須の参照を追加するための有名な</p> <pre><code>/// <reference </code></pre> <p>ラベルを追加するために必要とされた活字体の古いバージョンでは
- 2. THREE.Camera.prototype.lookAt</ <() -</ <はどういう意味ですか?
- 3. magentoバックエンドのconfig xmlデータを取得するにはどうすればよいですか?私は別のモジュールから、このラベルの値を取得したい</p> <pre><code><config> <sections> <dev> <groups> <my_module> <label>... </code></pre> <p>:
- 4. オブジェクトは、私は自分のアプリケーションで<code>infragistics</code><code>igGrid</code>を使用しているが、私は</p> </blockquote>「_super」プロパティまたはメソッドをサポートしていません<code>javascript</code>エラー</p> <blockquote> <p>オブジェクトを取得しています<p>igGrid
- 5. 列挙型の整数値を取得するにはどうすればよいですか?</p> <pre><code>enum Number { One = 1, Two = 2, Three = 3, Four = 4, } </code></pre> <p>が、どのような目的のために:
- 6. ファイルリダイレクトVS.</p> <pre><code>while(<>){ print; } </code></pre> <p>と私はこのようにリダイレクトしてファイルに渡す必要があります考えています:<code>./sort.pl < wordlist</code>を、それが持っている私はそうのようないくつかのファイルからSTDINにかかる<code>sort.pl</code>という名前のperlスクリプトを持って
- 7. gitブランチをマージして、一部のファイルで<<<<<<< HEADを取得してみてください。それはどういう意味ですか、どうすれば修復できますか?
- 8. <<を使用してクラスにファイルオブジェクトを供給するためにoperator <<を使用するにはどうすればよいですか?
- 9. オブジェクトリテラルのプロパティに直接アクセスすると、SyntaxErrorがスローされるのはなぜですか? <code>{}</code></p> <pre><code>{}.a </code></pre> <p>が、私はエラーを取得するには、オブジェクトのプロパティ<code>a</code>にアクセスしようとすると
- 10. コール私はAJAX呼び出しから取得し、私は<code>ng-repeat</code>を使用してdispledされる前に、各項目<code>line</code>プロパティ<code>line.date</code>のためにいくつかの変更が必要<code>lines</code>私はコレクションを持っている
- 11. AWSでホストされているWebアプリケーションでURL名を変更するにはどうすればよいですか? <code>xxprojectname.com</code>:ドメイン名に</p> <pre><code>[projectname.9zdecimvu4.us-west-2.elasticbeanstalk.com] </code></pre> <p>:
- 12. :私はシステムを入手する必要があり、コマンドラインから</p> <pre><code>kubectl get pods -o json </code></pre> <p>の出力からフィールドを取得するために、どのようにJSONをパースするjsonpath
- 13. ASP.NETコアEntity Frameworkのは、私は、関連するオブジェクトを取得しようとしていますたびに、私はオブジェクト</p> </blockquote> <p>関連するコードのインスタンスに設定されていないエラー</p> <blockquote> <p>オブジェクト参照を取得する関連データオブジェクト
- 14. 他の参照されていないプロジェクトからGUI要素にアクセスするにはどうすればよいですか? C#クラスライブラリプロジェクト</p></li> </ul> <p>B Aに参照されています</p> <ul> <li><p>プロジェクトA:</p></li> <li><p>プロジェクトBは、Windowsフォームアプリケーション
- 15. PGTとPGTIOUの保存CASが生成する
- 16. xamDataGridのフィールドは、私が使用して<strong><em>コンバータ</em></strong>内のフィールドの<strong>はAllowEdit</strong>プロパティを設定するために、<strong>xamDataGridの</strong>のフィールドに対して<strong><em>スタイル</em></strong>を作りたい
- 17. 文字列をクラス名に変換するにはどうしたらいいですか?私は、文字列<code>'TestClass'</code>与えられ、このファイルに<code>TestClass</code>を参照するにはどうすればよい
- 18. 変数に割り当てられた要求をエクスポートするにはどうすればよいですか?</strong></p> <pre><code><script> var electron = require('electron') </script> <app></app> <script src="bundle.js"></script> </code></pre> <p><strong>App.vue:
- 19. なぜGoogle Closure Compilerはオブジェクトのプロパティ名の名前を変更しますか?</p> <pre><code>var obj = JSON.parse(some_data); </code></pre> <p>をそして、<code>obj</code>プロパティ<code>x</code>持っていることが想定されています:
- 20. Heredoc <<<または<<?
- 21. 私はコードの下に使用して試してみました</p> <pre><code>@Document(indexName="Something",type="type") </code></pre> <p>で動的に<code>indexname</code>を取得しようとしています@Document
- 22. マウスは、マウスが<code>.wrap</code>、<code>.cube</code>と<code>.front</code>のために働いてではなく、<code>.left</code>、<code>.right</code>、<code>.top</code>、<code>.bottom</code>と<code>.back</code>のためにされ
- 23. 私はJSON <code>Array</code>を取得するために改造2を使用して、私は<code>ManagerListAdapter</code>(それは<code>RecyclerView</code>ためのアダプタです)新しい作成し、コンストラクタで(私はJSONから得た)<code>ArrayList</code>を渡したい
- 24. C#XML要素私は特に例えば<code><EmpTypeHeader></code>で<code>EmpList</code>タグの数と<code><EID>.</code></p> <p>を取得する必要がありますXMLノードに
- 25. CSVでは、列名をループしてヘッダー行の位置を取得するにはどうすればよいですか?私は私のRubyスクリプトで<code>require</code> D <code>csv</code>をしました</p> <pre><code>ID,Name,Age 1,John,99 </code></pre> <p>:
- 26. "<<<"演算子の名前は何ですか?
- 27. は、私は私のテーブル<code>new</code>にフィールド<code>photo</code>から<code>~\NewFolder1\</code>を削除する必要が
- 28. Typescriptオブジェクトの破棄は、「プロパティの割り当てが必要です。」という結果になります。コードから</p> <pre><code>error TS1136: Property assignment expected. </code></pre> <p>次のようになります:
- 29. Iはそれぞれに名前しようとしている</p> <blockquote> <p>VARテスト= [{...}、{...}、{...}]</p> </blockquote> <p>以下のように、私は変数を以下ているネストされたオブジェクトに
- 30. ツイストcallLaterは私が</p> <pre><code>reactor.callLater(5, my_func, self) </code></pre> <p>を行うとmy_funcに渡されたオブジェクトが、私はからcallLaterと呼ばれる自己ではないクラスのインスタンスで
を属性には一定の値が必要です。 –
@ DanielA.Whiteより正確には、**一定の**値。 –
これは機能しません。属性は一定の値を必要とし、あなたの 'PropName'プロパティは実行時にのみ評価されます –