3

私の Web クライアントは Json を送信します。MongoDB は実質的に Json です。簡単なはずですが、MVC3 の C# ドライバーとの闘いに苦労しています。C# クラスでの作業を避ける簡単な方法はないようです。少しフィルタリングしてJsonをやり取りするだけで簡単だと思っていたでしょう。私はORMと戦っているようなもので、なりたくありません。

とにかく、私は (しぶしぶ) C# でデータ モデルを構築しました。Json.Net を使用しており、シリアライゼーション コードは次のようになります。

JsonResult のシリアル化コードは次のとおりです。

public override void ExecuteResult(ControllerContext context)
{
    ...
    var serializedObject = JsonConvert.SerializeObject(Data, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
}

オブジェクトマッピングなしでこれを行う方法を理解することはできません。したがって、コントローラーアクションがあります。

public JsonResult test() 
{
    var col = _db.GetCollection<Project>("myCollection");

    var jsText = System.IO.File.ReadAllText(System.IO.Path.Combine(HttpContext.Server.MapPath("~/Controllers"), "MapReducers.js"));
    string map_cashflow = new Regex(@"//function map_cashflow(.*?)//end", RegexOptions.Singleline).Match(jsText).Captures[0].ToString();
    string reduce_cashflow = new Regex(@"//function reduce_cashflow(.*?)//end", RegexOptions.Singleline).Match(jsText).Captures[0].ToString();

    var mr = col.MapReduce(map_cashflow, reduce_cashflow);
    return Json(mr, JsonRequestBehavior.AllowGet); 
}

これは、他の場所でカーソルをシリアル化すると機能しますが (何らかの理由で)、基になるデータではなく実際の BsonDocument をシリアル化しようとしているため、上記が失敗することがわかりました。最初のフィールドを他の型としてシリアル化しようとすると、エラーが発生します。通常、文字列または日付を AsBoolean() に変換しようとします。ドライバーがドキュメントをもう少し簡単にシリアル化できないのは残念です。

オブジェクト グラフの動的な部分を表すために BsonDocument を使用しようとすると、同様の問題が発生しました。json文字列よりも優れていると思いましたが、もちろんシリアル化されません。Dictionary<> を使用することになりましたが、これは問題ありません。

これらも同様の結果で試しました。

return Json(mr.GetResults());
return Json(mr.GetResults()).ToArray();

そのため、人々が成功しているのを見た次のことも試しました。

var jsonText = mr.ToJson(); // empty
var jsonText = mr.GetResults().toJson(); // Exception: No serializer found for type System.Collections.IEnumerator.

私がやりたいのは、Jsonとほぼ同じように見えるものを元に戻すことだけですが、それをシリアル化する方法がわかりません。これが唯一の方法ですか?

var resultsObj = mr.GetResultsAs<ResultsClass>();

もしそうなら、それはひどいです。結果ドキュメントを格納するためだけに、静的に型付けされたクラスを構築したくありません。それは狂ったORMです!C# オブジェクトに出入りする必要はありません。ドライバーは実際には、助けというよりは邪魔になります。私はJsonをお願いします。

4

2 に答える 2

3

MVC3がその要件を課していない限り、これのためにオブジェクトモデルを作成する必要がある理由はわかりません。BsonDocument を使用し、JSON 文字列に直接シリアライズすることは問題ありません。投稿の大部分を読み進めるのは困難ですが、MapReduce を呼び出した結果に焦点を当てると、GetResults() メソッドは IEnumerable<BsonDocument> 型の値を返します。これは簡単に JSON に変換できるはずです。簡単なテストを次に示します。

IEnumerable<BsonDocument> results = new BsonDocument[] 
{
    new BsonDocument("x", 1),
    new BsonDocument("x", 2)
};
var json = results.ToJson();

このコードを実行すると、json 変数は次の内容になります。

[{ "x" : 1 }, { "x" : 2 }]

特に、あなたが言及した例外はありません。十分に新しいバージョンの C# ドライバーを使用していることを確認できますか? それでも例外が発生する場合は、完全なスタック トレースを返してください。

問題の一部は、BsonDocument と、C# ドライバーの一部ではない JSON シリアライザーを混在させて一致させることから発生している可能性があります。サード パーティの JSON シリアライザー (使用している JsonResult を返す Json メソッドなど) は通常、シリアル化できるものとできないものに独自の制約を課します。したがって、発生している問題は、MongoDB C# ドライバーの外部にあるように見えます。

申し訳ありませんが、私は MVC3 と、結果を JSON に変換して戻す方法について十分に理解していません。

于 2012-04-06T01:11:16.980 に答える
1

そこで、ドキュメント自体で toJson() メソッドを使用して BsonDocuments をシリアル化できるようにする、Json.Net 用の一方向プラグインを作成しました。2 つの異なるシリアライザー スタックがあるため、これは理想的ではありません。

public class BsonDocumentConverterPlugin : Newtonsoft.Json,JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        BsonDocument bsonDoc = (BsonDocument)value;
        writer.WriteRaw(bsonDoc.ToJson());
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Serialisation back to Bson not supported in this converter");
    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(BsonDocument));
    }
}

そして私の JsonResult オーバーライドで;

        var serializedObject = JsonConvert.SerializeObject(Data, Formatting.None, 
                new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore,
                                             Converters = new List<JsonConverter>() { new BsonDocumentConverterPlugin() }
                });

残念ながら、これは複数の結果を持つ MapReduce 結果セットでは機能しないようです。これは、使用するシリアル化方法に関係なく、それらを配列としてシリアル化せず、コンマを見逃して無効な json になるためです。BsonDocument.ToJson() は、日付に対して無効な json も書き込みます。strict では ISODate() と書き、JavaScript/TenGen では newDate() と書きます。これらの両方により、ブラウザがバーフします。

結局、オブジェクト グラフの作成に頼らざるを得なくなりました。

    public class MrResultsetCashflow
    {
        [MongoDB.Bson.Serialization.Attributes.BsonId]
        public DateTime date { get; set; }
        public FinancialItem value;
    }

元の MVC/json.net シリアライゼーション スタックを調べます。

        var f = mr.GetResultsAs<MrResultsetCashflow>();
        return Json(f, JsonRequestBehavior.AllowGet); 
于 2012-04-06T15:22:36.087 に答える