質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

Q&A

解決済

13回答

25475閲覧

多段構造になっているハッシュテーブルの取り扱いについて

ShintaroIshida

総合スコア87

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

0グッド

2クリップ

投稿2015/05/11 09:40

編集2015/05/12 04:34

以下のような多段構造をした構造体を定義しました

lang

1public class ListModel 2{ 3 public Dictionary<string, string> A = new Dictionary<string, string>(); 4 public Dictionary<string, string> B = new Dictionary<string, string>(); 5 public Dictionary<string, Dictionary<string, string>> C = 6 new Dictionary<string, Dictionary<string, string>>(); 7 public Dictionary<string, List<Dictionary<string, string>>> D = 8 new Dictionary<string, List<Dictionary<string, string>>>(); 9ring, object>(); 10public Dictionary<string, object> dic = new Dictionary<string, object>(); 11// コンストラクタ 12 public LayoutModel(){ 13 this.dic = new Dictionary<string, object> { 14 {"A", A}, 15 {"B", B}, 16 {"C", C}, 17 {"D", D} 18 }; 19 } 20}

上記の構造体を以下のよう処理で取扱いたいと思っています。

lang

1// この返却値指定もおかしいですよね?( 2public ListModel Main(){ 3 4 ListModel list = new ListModel(); 5 List<string> KeyList = {"A","B","C","D"}; 6 7 foreach( string ListKey in KeyList ) 8 { 9 // エラーが出ます。。。当たり前ですよね。 10 list.dic[ListKey].Add( ListKey, "テストです" ); 11 } 12 13 // ここの返却値の型の指定の仕方もわかりません。(ListModel.dic を返したいです) 14 return list; 15}

何がやりたいの?という話なのですが、
画一的な構造ではなく、様々な多段構造をもつハッシュテーブルを
一定のルールに従い本処理で取扱いたいのです。
※出現したkeyによってif or switch 等で条件分岐するような泥臭い方法は極力行いたくない

C#(OR 型の制約がある程度厳密な言語で普段開発される方)は、こういったケースの場合
どのような実装方法(型定義も含めて)で、こういった問題をクリアするのでしょうか?

自分は、PHPから入ったので連想配列辺りのこの辺の処理はあまり意識して組んだことがありません。(データ生成後のアクセスのしやすさは考慮しますが、データ生成の時点では特に型・構造は意識しなくてよいので)

技術的な方法でこういった問題を解決する事ももちろん知りたいのですが、
漠然と感じているのは、そもそもの設計思想だと思っています。
そういった部分も含めて言及・ご意見頂けると大変ありがたいです。

一応、上記処理を利用して作るデータのイメージを掲載します。

lang

1dic: { 2 A: { 3 A-DATA: "123" 4 } 5 B: { 6 B-DATA-1: "B TEST" 7 B-DATA-2: "B 2 TEST" 8 } 9 C: { 10 C-1-DATA: { 11 C-DATA-1: "hogehoge" 12 } 13 } 14 D: { 15 A-D: [{"A":"a"},{"B":"b"}],[{"A2":"a2"},{"B2":"b2"}] 16 B-D: [{"A":"a"},{"B":"b"}],[{"A2":"a2"},{"B2":"b2"}] 17 C-D: [{"A":"a"},{"B":"b"}],[{"A2":"a2"},{"B2":"b2"}] 18 } 19}

追記:
質問内容に記載したデータをどのようにシリアライズするかどうかはわかっています。
JSONがどうとか、SOAPだXMLだとかの質問をしているわけではないです。
以下の内容がわかれば知りたいです。

・C#で、各要素に構造の違うハッシュテーブルを詰め込む方法
・最上位 VALUEにobjectで引き渡す事は出来るが引き渡した後に各要素への値追加の方法がわからない

出来るのであれば出来る方法を出来ないのであれば、こういったニーズが発生した場合どういう風に対処するのかが知りたいです。

自分が、コメントに対してJSONで利用すう前提という事を記載してしまったのがいけないのですが
JSONでデータ通信は問題なく出来ていますので、その辺への言及は大丈夫です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

katzC4ISR

2015/05/11 09:50

C#でJSONを使いたいのではないか,と推察いたしますが,いかがでしょうか?
ShintaroIshida

2015/05/11 09:56

katzC4ISR 様 ご推察通り、まさにその通りです! 仕様変更があった場合、構成情報を構造体や外部XML等で管理して本処理になるべく手をつけたくないので、苦肉の策なのですが。。。
katzC4ISR

2015/05/11 11:02

そうでしたか:-) ちょうど,数日前に私も同じ状況に遭遇したので,もしやと思ったのです. ということであればC#でのJSONの扱いをちょうどまとめたところだったので,情報を紹介いたします.
guest

回答13

0

自己解決

投稿からかなり期間が経過してしまいましたが、
様々な方のご意見を受けて自分なりに問題の解決出来たので
簡単にですが実現方法を掲載しておきます。

1.データ構造をクラス化して対応しました
データ構成もですが、主に各々の階層へpushするメソッドを準備しました。

2.データの準備の順番を見直しました
最初、php的な考え方が抜け切れておらず、最初に最上位にあたるハッシュを定義した上で
二段階目の要素へデータを追加し続けるという方法で実装していたのですが、
要素[A・B・C・D]に格納する予定のハッシュを先に構築し、全ての要素を
準備した後に最上位のハッシュへ各生成したハッシュを格納する事で対応しました。

多段階層をもつハッシュを最初に定義した + その階層へのアクセス方法を
カプセル化できていなかったので、想定している動きが実装出来なかったという事でした。

結果的には、もっと効率が良かったりする方法もあるかと思いますが
自分としては、最低限実現したかった方法が実装できたので満足しています。

また、多くの方に様々なご意見を頂きまして色々な部分で勉強になりました。
特に質問投稿初期からご意見を再三に渡り頂きました

Tak1wa 様
katzC4ISR 様
haru666 様

ありがとうございました。

投稿2015/06/17 15:52

ShintaroIshida

総合スコア87

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

見も蓋もない話ですが、まずはC#の一般的なコーディングルールを学ぶ方が妥当だと思います。

C#ではこのようにDictionaryをネストしないのが普通です。
Jsonに一定のルールを決定することがC#ではクラスの定義に相当します。
Jsonの連想配列は型の宣言こそありませんが、皆さん型自体は無意識ながら決めていると思います。
やれこのデータ型は文字列である、数値である、別のオブジェクトである、ということを分かって使っているはずです。
これを先に宣言するのがC#です。

C#で連想配列を扱うのは、連想配列でなくてはならない場合のみです。
クラス⇔Json の変換にはJson.NETを使用するといいと思います。
まずC#のクラスについて勉強し、その後Json.NETの利用方法を確認してみてください。
Json.NETの利用方法は、C#とJsonの違いを教えてくれると思います。

投稿2015/05/12 01:24

編集2015/05/12 01:33
haru666

総合スコア1591

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShintaroIshida

2015/05/12 04:17

回答ありがとうございます。 頂いたご意見をよく読んでみたのですが、以下の点が理解出来ません。 >C#ではこのようにDictionaryをネストしないのが普通です。 この普通というのはどのようなケースを指されているのでしょうか? 単純にハッシュテーブルのネストであれば実装方法が存在するので 言語として対応してないわけではないと思うのですが。。。 >C#で連想配列を扱うのは、連想配列でなくてはならない場合のみです。 これは、このような多様な仕様を満たす想定であればそれようのクラスを定義すべき という事でしょうか? 他の内容に関しては、回答を頂いておきながら大変申し訳ありませんが、 そもそも理解しているので、大丈夫です。(一応、PHP・RubyでJSONを使ったRESTの実装したことありますので。。)
haru666

2015/05/12 05:37

>> C#ではこのようにDictionaryをネストしないのが普通です。 > この普通というのはどのようなケースを指されているのでしょうか? 一般的なC#のコーディングを行う上での話をしているつもりです。 Dictionary型をネストするぐらいなら通常はクラス自体をネストします。 > 画一的な構造ではなく、様々な多段構造をもつハッシュテーブルを > 一定のルールに従い本処理で取扱いたいのです。 上記のように書かれていますが、本当にそれらは連想配列の形式を保持しつづける必要があるのでしょうか。 「様々な多段構造をもつ」というのが様々なクラスの複合体である、というように読めます。 Jsonの時にきちんとした利用方法があるなら一度クラスに落とし込むことができるはずです。 Dictionary型を利用するということは型の情報を保持しないと意味するのと殆ど同義です。 Dictionary型を利用することで以下のデメリットが発生します。 ・他の開発者が見てどのようにクラスを扱うかが分からない ・型情報からどのようなメンバ(Key)が登録されているかわからない ・C#の強力な型リフレクション機能が使えない ・インテリセンスが使えない 他にもコンストラクタが使えないとか、Keyが登録されている/いないという3値論理のような問題が組み込まれてしまうとか、デメリットは沢山あります。 >> C#で連想配列を扱うのは、連想配列でなくてはならない場合のみです。 > これは、このような多様な仕様を満たす想定であればそれようのクラスを定義すべきという事でしょうか? そうです。基本的にはクラスを定義すべきです。 エンドユーザーが独自に定義できるインタプリタをC#内に実装しているとか、そういう場合でなら連想配列を使います。 例えば、メールの定型文機能とか、ASP.NETにおけるURLと機能のマッピングであるとかですね。 こういう場合、Dictionary型のKeyValuePairの扱いも一定になります。 ある「Key」の場合「Value」はこんな風に扱わなくてはならない、ということがルールとして存在するなら、Dictionary型を使ってはいけません。 それはクラス化するに足る制約をDictionaryに付加しています。 もちろん細かく見ていけば例外もあります。 ただ安易にDictionary型を使う、ということであれば「それはC#らしくない」と言わなければならないでしょう。
ShintaroIshida

2015/05/12 23:56

詳細に返答頂きありがとうございました。 >「様々な多段構造をもつ」というのが様々なクラスの複合体である、というように読めます。 >Jsonの時にきちんとした利用方法があるなら一度クラスに落とし込むことができるはずです。 確かにおっしゃられる通りだと思います。 コメント頂き思ったのが、自分の中でクラスというものは、処理を実装してそれを切り分ける際に(拡張性を持たせる)作成するものという先入観があったと思います。 よくよく考えてみるとそもそも構造体自体もクラスなわけですから汎用的な位置づけで利用するのであればクラスの利用を検討すべきですね。 >エンドユーザーが独自に定義できるインタプリタをC#内に実装しているとか、そういう場合でなら連想配列を使います。 >例えば、メールの定型文機能とか、ASP.NETにおけるURLと機能のマッピングであるとかですね。 まだちょっと haru666 様が、おっしゃられるハッシュの使いどころはおぼろげですが、 これはC#を使い倒していくうえで自分自身に覚えこませていこうと思います。 (今までの言語も全てそうだったので。。。) >それはクラス化するに足る制約をDictionaryに付加しています。 まずはここを念頭において、クラス設計の見直しをやってみようと思います。
guest

0

なるほど,アプローチは2つあると思います

  1. DBから読み込むデータを受け取るエンティティクラスを定義する.このエンティティをDataContract~等でJSON文字列化する
  2. そうではなくて,DBから読み込むデータ構造が多様なので,逐一エンティティクラスを定義したくない,そこでJavaScriptのように連想配列と配列を組み合わせた汎用的なエンティティクラスがあればよい.

2)のアプローチの場合は,どうすればいいか?ということですね?
これはですね.私もそう思います.

Windows.Data.Json クラス
https://msdn.microsoft.com/ja-jp/library/windows/apps/br229889.aspx

残念ながらこのクラスをどうやって使えばいいかが,どうしてもわかりませんでした.
Windows8や2012では使えるようなのですが...

なので,自分で実装しました.Windows.Data.Jsonの仕様のように,
JSONValueのためのインターフェースを定義して(プリミティブ値,配列,連想配列すべてを表す)

インターフェースを実装したJSONObject,連想配列を持つDictionary<String, JSONValue>
JSONArray,配列を持つList<JSONValue>

たとえば,{"Key":"Value"} の場合は,JSONObject.Add(”Key”,"Value")
{"Key":["Value"]} の場合は,JSONObject.Add(”Key”,JSONArray.Add("Value"))
["Key1":{"Key2":Value}] の場合は,JSONArray.Add("Key1", JSONObject.Add(”Key2”,Value)

こういった形で使いました.

投稿2015/05/12 00:49

katzC4ISR

総合スコア66

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShintaroIshida

2015/05/12 04:07

回答ありがとうございます。 >たとえば,{"Key":"Value"} の場合は,JSONObject.Add(”Key”,"Value") >{"Key":["Value"]} の場合は,JSONObject.Add(”Key”,JSONArray.Add("Value")) >["Key1":{"Key2":Value}] の場合は,JSONArray.Add("Key1", JSONObject.Add(”Key2”,Value) やはりそういう方法に行きつくのですね。 最初にご提示いただいた様な方法で実装していたのですが、 ソースが冗長になる+仕様変更の度に処理を追加しないといけないという問題に気が付いて実装方針を改めて今回の様な質問に行きつきました。 そもそもの仕様がとか、JSONがどうとかというご意見も頂いていますが、 ハッシュテーブル自体は、言語の仕様としてネストして定義出来るのであとはデータをどのように追加していくか?だけだと思っていたのですが、中々思ったような情報に行きつかない現状です。。
katzC4ISR

2015/05/12 08:05

うーん.ちょっと私が,JSONを出してミスリーディング(みなさんを)してしまったのかもしれないですね.話を巻き戻しましょうか.別の回答を立てますね.
guest

0

一つのDictionaryにValueやネストしたDictionaryを入れ、複雑な構造を作りたいということですか?
その場合、最も適切な方法は、Dictionary<string, dynamic>でDictionaryを宣言し、各要素の追加を行います。
ネストさせるDictionaryも全て<string, dynamic>で作成する必要があります。
インテリセンスが効かなくなる問題はありますが、ネストしたDictionaryに値を追加するときもAddを使うだけで済みます。
動的な構造変更をしていることになるので、型が一致しているかどうかを管理するのはプログラマの責任となります。

lang

1var dict = new Dictionary<string, dynamic>(); 2dict.Add("A", new Dictionary<string, dynamic>()); 3dict.Add("B", new Dictionary<string, dynamic>()); 4dict.Add("C", new Dictionary<string, dynamic>()); 5 6dict["A"].Add("1", "ABCDE"); 7dict["A"].Add("2", "FGHIJ"); 8dict["B"].Add("x", "test"); 9 10dict["C"].Add("AAA", new Dictionary<string, dynamic>()); 11dict["C"]["AAA"].Add("1", "hogehoge"); 12 13var value = dict["A"]["1"]; // -> value = "ABCDE"

静的な型付けを持つC#で構造の違うオブジェクトを同様に扱いたい場合はobjectかdynamicを使うか、ジェネリックな入れ物を作成する方法で対応できます。この用途で使える入れ物の作成方法はここには書きませんが、結局は型消去をするので値の取り出しにキャストが必要になり、あまり有用ではありません。

投稿2015/05/16 06:47

tamoto

総合スコア4105

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

エラーが出るのは宣言された型と入力されるデータに互換性がないからです。
試しに「テストです」の部分を null に変えたらうまくいくのではないですか?

AおよびBのデータ型は文字列なので、文字列である「テストです」は代入できます。
CおよびDのデータ型はDictionary<string, string>なので、文字列は代入できません。

多段構造とかハッシュテーブルとか言う以前の問題だと思います。
なんでも代入できる変数が欲しければ、object あるいは dynamic を使うべきでしょう。

投稿2015/05/15 03:34

Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2015/05/18 06:29

なぜか-1されていますが、背伸びしすぎて問題の分離ができていないように見受けられます。 A は Dictionary<string, string> なので、string をキーとして string のデータを代入できます。 C は Dictionary<string, Dictionary<string, string>> なので、string をキーとして Dictionary<string, string> のデータを代入できます。 あなたの質問ではこのどちらにも string のデータを代入しようとしています。 これがエラーの原因です。 ここを理解してから多段構造を勉強するのが近道だと思います。
guest

0

うーむ、難しい話になってきましたね。

・C#で、各要素に構造の違うハッシュテーブルを詰め込む方法
・最上位 VALUEにobjectで引き渡す事は出来るが引き渡した後に各要素への値追加の方法がわからない

まずJSONのことはキッパリ忘れますね。
上記をやりたいだけであれば、
Dictionary<string, IDictionary>にしてやれば詰め込めます。

ただし再帰的にDictionaryまたはValueとして扱いたいのでしょうから、
以下のようにDictionary自体を作成して、object型の部分をカスタムクラス内で吸収してやれば実装自体は出来る気がしてます。

lang

1public class DictionaryEx : Dictionary<string, object>, IDictionary<string, DictionaryEx>, IDictionary<string, string>

↑頓珍漢なこと言ってました。試してみましたがダメっぽかったです。


ここからJSONを前提とした話にちょっと戻ります(お気に障ったらすみません)

質問内容に記載したデータをどのようにシリアライズするかどうかはわかっています。

私が勘違いしていたら申し訳ないのですが、皆さんが仰っているのでは逆の話で、
クライアントから受け取ったJSON文字列を、ASP.NET側でフレームワークを用いてデシリアライズしてやれば、

Dictionary型をネストするぐらいなら通常はクラス自体をネストします。

とするだけで簡単に出来るしスマートだし変更にも強いよ、と言っているのだと思います。

質問文の最初に

lang

1foreach( string ListKey in KeyList )

とありましたが、ひょっとしてループでぐるぐるとJSON⇔POCOの変換をかけようとしていませんか?

↑ これも私の検討違いかも…。質問者さんはデシリアライズのことについては触れてませんでしたね。

本回答は無視してください。失礼しました。

投稿2015/05/12 10:28

編集2015/05/12 10:54
Tak1wa

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C#で、各要素に構造の違うハッシュテーブルを詰め込む方法

これ同じ事考えていろいろ試したことがあるのですがデータクラスはobjectで定義しておいて処理を行うメソッドをジェネリックにして使うのが私の限界でした。

objectを型パラメータで指定された型にキャストして、ごにょごにょ処理をすると。
型制約とかで「一定のルール」の範囲を絞ることも出来ると思います。
ただ、型増えるわ共通化しすぎていろんなところで依存しまくるわ(設計が悪いだけかもしれないけど)・・・・これだったらLinqつかっちゃったほうが早いなぁと今は思ってます。。。

最上位 VALUEにobjectで引き渡す事は出来るが引き渡した後に各要素への値追加の方法がわからない

リフレクションで呼んであげれば良いんじゃないかな
ttp://dobon.net/vb/dotnet/programing/typeinvokemember.html

イメージ的にはアンマネージDLLのメソッド使う感じでメンバを呼び出す感じ。
当然使われる側の正確なメソッドの定義を使う側が知っている必要があります。

総じて「どんな構造であるか使う側が知らないでその構造には触れない」ってのが一般論かと。
究極的には上のリフレクションでメンバ名を「文字列」で扱うことが出来るんで、動的に構造を解析して操作することも出来なくはないと思いますが・・・・まぁ業務アプリでそんなの作ったら普通怒られますよね・・・

以上

投稿2015/05/12 09:39

編集2015/05/12 09:40
Ryzna

総合スコア85

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShintaroIshida

2015/05/13 00:32

回答ありがとうございます。 >データクラスはobjectで定義しておいて処理を行うメソッドを >ジェネリックにして使うのが私の限界でした。 なるほど。そういった実装方法もあるのですね。 ジェネリックの概念については、回答を頂いてから知りました。 >ただ、型増えるわ共通化しすぎていろんなところで依存しまくるわ >(設計が悪いだけかもしれないけど)・・・・これだったらLinqつかっちゃったほうが早いなぁと今は思ってます。。。 自分も処理の共通化を念頭において今回のような考えに至ったのですが、依存の弊害も確かに考慮しないといけないですね。 >リフレクションで呼んであげれば良いんじゃないかな 一応考えはあったのですが、データ=変数という自分の中の先入観があったのもありまして、なんだかなぁ~と思ってスルーしていました。 haru666様の回答~コメントを頂いて自分の中の先入観に気づく事が出来たので、リフレクションも検討しようと思います。 >総じて「どんな構造であるか使う側が知らないでその構造には触れない」ってのが一般論かと。 確かにその通りだと思います。実際、型制約が緩い言語ですとその辺の弊害が意図しない形で発生する認識はあるので。 >究極的には上のリフレクションでメンバ名を「文字列」で扱うことが出来るんで、動的に構造を解析して操作することも出来なくはないと思いますが・・・・まぁ業務アプリでそんなの作ったら普通怒られますよね・・・ ここの普通怒られるという部分がよくわかりませんでした。 例えば、ビジネスロジック側は基本的に変更しない。 処理対象となるデータをXMLやDBに準備して、処理対象の管理をするという方法は 問題になるという事でしょうか?であれば、どういったケースが想定されるのでしょうか?質問とは異なる疑問ですが、お手数でなければ教えて頂けますと幸いです。
Ryzna

2015/05/13 01:36

>ここの普通怒られるという部分がよくわかりませんでした。 >例えば、ビジネスロジック側は基本的に変更しない。 >処理対象となるデータをXMLやDBに準備して、処理対象の管理をするという方法は 問題になるという事でしょうか? すみません。もっと無制限的な意味で、特に深い意味はないです。 ご提示頂いた例は仕様に基づく設計なり実装なりだと思うので必要なことだと思います。 仕様に基づく構造の範囲を逸脱して動的にデータ構造解析してそれを良しとするのは良くないよねぇ・・・という意味でした。 しかし改めて考えてみると生データからデータオブジェクト起こす解析部分は無制限にしておいて、データ構造が仕様に基づいているか判断部分を別に設ければ良いのかなぁ・・・と思いました;その程度なのであまりおきになさらず;
Ryzna

2015/05/13 01:49

追記です。 データ構造が何でも受け入れられる必要があるのって、異なる構造が同時に使用される場合だと思いますが、その場合はパターン識別による構造管理が必要になります。簡単なアプリだとそれをクラス名やら構造体名やらで識別するわけですが、動的に生成される構造はこれらが使えなくなります=言語的な制約のサポートを受けれなくなります。私自身それを良しとするプロジェクトに参画したことが無いのも理由の一つです。(尚私は経験貧弱です;)
Ryzna

2015/05/13 04:48

サンプル作ってみました。 ↓↓↓↓↓↓ // 連想リスト public class DictionaryEX : Dictionary<string, object> { public bool GetValue<T>(string key, out T value) { var result = false; try { value = (T)this[key]; } catch { // キーが無い場合、キャストできない場合はどうするか考える必要がある value = default(T); } return result; } public T GetValue<T>(string key) { return (T)this[key]; } } // おまけでリスト public class ListEx : List<object> { public bool GetValue<T>(int index, out T value) { var result = false; try { // キーが無い場合、キャストできない場合はどうするか考える必要がある value = (T)this[index]; } catch { value = default(T); } return result; } public T GetValue<T>(int index) { return (T)this[index]; } } static void Main(string[] args) { // データを作ってみる var val1 = new DictionaryEX(); var val2 = new DictionaryEX(); var val3 = new DictionaryEX(); var val4 = new ListEx(); var val5 = "Val5"; var val6 = (short)6; var val7 = true; val1.Add("Value1", val1); val1.Add("Value2", val2); val1.Add("Value5", val5); val1.Add("Value6", val6); val1.Add("Value7", val7); val2.Add("Value3", val3); val2.Add("Value5", val5); val2.Add("Value6", val6); val2.Add("Value7", val7); val3.Add("Value4", val4); val4.Add(val5); val4.Add(val6); // 上の処理で出来上がるデータをXML風に表現 // <Value1> // <Value1> // 無限ループなので省略 // </Value1> // <Value2> // <Value3> // <Value4> // <Value4Item>Val5</Value4Item> // <Value4Item>6</Value4Item> // </Value4> // </Value3> // <Value5>Val5</Value5> // <Value6>6</Value6> // <Value7>true</Value7> // </Value2> // <Value5>Val5</Value5> // <Value6>6</Value6> // <Value7>true</Value7> // </Value1> // 実際にアクセスしてみる Method(val1); } static private void Method(DictionaryEX collection) { var val1 = default(DictionaryEX); var val2 = default(ListEx); var val5 = default(string); var val6 = default(short); var val7 = default(bool); collection.GetValue("Value1", out val1); collection.GetValue("Value2", out val1); collection.GetValue("Value3", out val1); // 内部でランタイムエラー(キー無し) collection.GetValue("Value5", out val1); // 内部でランタイムエラー(キャスト不可) collection.GetValue("Value7", out val7); // 一歩ずつ。戻り値チェックして堅実に(チェック省略) collection.GetValue("Value2", out val1); val1.GetValue("Value3", out val1); val1.GetValue("Value4", out val2); val2.GetValue(0, out val5); val2.GetValue(1, out val6); // 直列で一気に。例外なんて怖くない。 val5 = collection.GetValue<DictionaryEX>("Value2") .GetValue<DictionaryEX>("Value3") .GetValue<ListEx>("Value4") .GetValue<string>(0); } ↑↑↑↑↑↑ チャレンジしたころの記憶を掘り起こしてサンプル作ってみました。 まぁ要するにキャストしてるだけですが・・・・
guest

0

・C#で、各要素に構造の違うハッシュテーブルを詰め込む方法
・最上位 VALUEにobjectで引き渡す事は出来るが引き渡した後に各要素への値追加の方法がわからない

this.dic = new Dictionary<string, object> {

ここがobject型なので,値を取り出したところでそのままでは構造の違うハッシュには格納してくれませんね.

すみません,元のコードに戻って

list.dic[ListKey].Add( ListKey, "テストです" );
の時に、ABCDそれぞれどのような動きをさせたいですか?

ここから再開いたしましょう.たとえば,このAddが成功したとして,
ABCDはどのように変化してほしいですか?

投稿2015/05/12 08:23

katzC4ISR

総合スコア66

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

汎用的なツリー構造の型付きデータを扱いたいという要望なら、
XMLとSOAP通信を行うのが一般的だと思います。
XMLの仕様は DTDや XML Schema やら RELAXやらで定義します。

私企業・公的機関 を超える標準データ交換規約ではよく用いられますね。
例えば メタボ健診のデータの
http://www.mhlw.go.jp/bunya/shakaihosho/iryouseido01/info02i.html
とか、
ヤマト運輸の送り状データなんて一風変わったものも
http://www.kuronekoyamato.co.jp/newb2/help/manual/manual_sosa/16_exchange/exchange_01.html
とか。

で、こういう DTDやら XML Schema のスキーマをもらえれば、
動的にXMLをパースできてしまうので、実質上あらゆる階層化データを
扱えることになります。SOAPなんかはそのための通信規格ですね。

単にブラウザとサーバで同じデータモデルを扱いたい、ということであれば、
サーバ側のクラス定義をそのまま ブラウザ側とやりとりする、という
仕組みはいくつもありますね。
ASP.Netなら 古くは AJAX Extensions から、
今は ASP.Net MVCで提供されているんじゃないでしょうか。

たとえば、いいまとめ記事があります。
http://qiita.com/kazuhisam3/items/94542f6d7ccf3acca41c

ただ、他の回答者も指摘されているとおり、サーバ側できちんとモデル定義をすることは必要です。
それは C#だから 型付き言語だからというのではなく、PHPでもそうだったはずですけどね。

投稿2015/05/12 02:51

okayu3

総合スコア200

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShintaroIshida

2015/05/12 04:27

回答ありがとうございます。 >今は ASP.Net MVCで提供されているんじゃないでしょうか。 ご指摘通り、大枠のプロジェクトはASP.NetのMVCで構築しております。 XMLが何か?SOAPがどういった通信を行うかは、言語に偏った話ではありませんので、 理解しているつもりです。 参考の記事までありがとうございます。 現状としては、MVCモデルを利用したJSONデータの受け取り(REST)は出来ています。 質問させて頂いているのは、あくまでも内容に記載しているようなハッシュテーブルの取り扱いに関してです。 >ただ、他の回答者も指摘されているとおり、サーバ側できちんとモデル定義をすることは必要です。 確かにそうですね。ただ今回の場合、受け取り側のクライアントが提示した仕様ですので極力手を入れたくありません。プラス、仕様変更に柔軟に対応出来る実装を行いたいのです。実現可能な方法を提案する事も最終的には考えていますが。 >それは C#だから 型付き言語だからというのではなく、PHPでもそうだったはずですけどね。 おっしゃられる通りですが、厳密に言うとPHPにもちゃんとデータ型の概念は存在します。ただ、配列や連想配列の取り扱いに関してはかなり直感的に扱えます。(悪く言えば適当に実装しても動く) 今回の質問は、そういった部分を質問させて頂いております。 分かりづらい質問で大変申し訳ないです。
guest

0

どうも,改めまして.

C#でJSONを扱うには,幾つか選択肢があります.以下,Webに出回っている情報のポインタになりますが,ご紹介いたします.
おおむね
http://www2.hatenadiary.jp/entry/2013/12/14/030112
によくまとめられています.

概要をお話いたしますと,
0. ちゃんとJSONを扱いたい > Json.NET, DynamicJSON
0. ある程度固定の情報のJSONを扱いたい > System.Runtime.Serialization.Json(JsonReaderWriterFactory, DataContractJsonSerializer)や, System.Web.helpers.JsonやSystem.Web.Extentions.dllのJavaScriptSerializerを使う

ということのようです.

.NET Framework < 3.5
Json.NET

http://www.newtonsoft.com/json

Json.NET/デシリアライズ支援サイト

http://json2csharp.com/

.NET Framework 3.5 から

System.Service.Modelを参照に追加しよう.

System.Runtime.Serialization.Json JsonReaderWriterFactory DataContractJsonSerializer http://msdn.microsoft.com/ja-jp/library/bb412179(v=vs.110).aspx http://jsontodatacontract.azurewebsites.net/ DataContractJsonSerializerで不定形のJSONデータを読み込む

.NET Framework 4.0 から
DynamicJSON

http://neue.cc/2010/04/30_256.html

.NET Framework

System.Web.helpers Json System.Web.Extentions.dll JavaScriptSerializer

投稿2015/05/11 11:09

katzC4ISR

総合スコア66

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShintaroIshida

2015/05/11 23:51

回答ありがとうございます。 JSONのでのデータの取り扱いは問題がなくて、(ASP.Netで問題なく取り扱えています)JSONでデータを送る前のデータ生成部分の問題になります。 どちらかというと、objectの取り扱い方という事になると思っています。 ハッシュテーブルの階層をネストして定義していくのはわかるのですが、 ```lang-<C#> new Dictionary<string, object> dic = new Dictionary<string, object> { {"A", A}, {"B", B}, {"C", C}, {"D", D} }; ``` 質問に投稿している構造体を持った上記のようなハッシュテーブルを作成した場合、 どういう風に要素を追加していけばよいのかがわかりません。 そもそも値をobjectで乗せているのが問題なのか? (A~DのDictionary構成がそれぞれ違うので苦肉の策で上記のような引き渡しをやっています) 仮に上記の定義が通常であれば、dic生成後の各二次元以下への要素の追加はどのように行えばよいのか?が、 今回知りたい事になります。 (質問にも書きましたがそもそもこのようなハッシュテーブルの扱い方?が問題であるとも思っています。 設計思想がダメなような) 自分の質問がわかりづらくお手を取らせてしまい大変申し訳ありません。
Tak1wa

2015/05/12 00:05

設計思想という意味では、katzC4ISRさんが仰っているように、DataContractJsonSerializerなどを使用してJSON文字列⇔エンティティのシリアライズ、デシリアライズを行うのが一般的です。 Dictionaryを使って入れ子にしているのは何故でしょうか? 差支えなければ教えてください。
katzC4ISR

2015/05/12 00:16

オブジェクトをシリアライズしてJSON文字列にはできるけれども, そのオブジェクトとして,RubyやJavaScriptのように,連想配列と配列を 組み合わせてデータを保持したい.のだけれども, どのように,クラスを定義すればよいか? そのクラスではどのようなメソッド実装で要素を追加すればいいか? こういうことでしょうか?
ShintaroIshida

2015/05/12 00:18

Tak1wa様 コメントありがとうございます。 >Dictionaryを使って入れ子にしているのは何故でしょうか? 送信部分の仕様で、最終的にJSONにシリアライズするのですが、シリアライズ前のデータは、DBから取り出すデータになります。 受け取り側の仕様に準じてデータの構造を組むと、今回のような形式でデータを加工して 最終的にJSONデータに書き換えると言った流れになります。
ShintaroIshida

2015/05/12 00:24

katzC4ISR 様 まさにその通りです! 付け加えますと、構造で例に出している A~Dハッシュの単体の構成であれば 問題なく実装出来ているのですが、dicハッシュにそれらのハッシュテーブルを当て込んだ後、どのように要素を追加していけばよいのか? そもそもこういったやり方自体が問題なのか?がわかっていません。 再三に渡り、わかりづらい質問をご理解頂き端的に解して頂いてありがとうございます。
Tak1wa

2015/05/12 00:29

なるほど。 では、クライアント側の仕様に合わせた形式でJSONを組み立てたいのですね? であればクライアントの仕様にあわせたエンティティを用意しDataContractJsonSerializerでエンコードしてやっては如何ですか?
ShintaroIshida

2015/05/12 01:08

Tak1wa様 コメントありがとうございます。 >クライアントの仕様にあわせたエンティティを用意し これが質問に投稿したソースです。上記の別回答で katzC4ISR様がおっしゃっている通り、TBLが多種多様な構造なので、それらをビジネスロジック側で整理⇒一本化して、質問に記載している処理で、纏め上げたいというのがやりたいことです。 分かりづらくて申し訳ないです。
guest

0

操作ミスです

投稿2015/05/11 10:10

編集2015/05/11 10:11
ShintaroIshida

総合スコア87

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

これも誤動作です

投稿2015/05/11 10:08

編集2015/05/11 10:23
ShintaroIshida

総合スコア87

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

一定のルールに従い本処理で取扱いたいのです。

この一定のルールが事前に決まっていれば可能だと思います。

例えば、
list.dic[ListKey].Add( ListKey, "テストです" );
の時に、ABCDそれぞれどのような動きをさせたいですか?

投稿2015/05/11 09:55

Tak1wa

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ShintaroIshida

2015/05/11 10:16

回答ありがとうございます。 一定のルールに関してですが、明確なのは、A・B・C・D 各階層の最下部にDBから取得したデータを格納したいです。Aが基礎情報格納部分だとしたら、C・D辺りは詳細情報保持する部分という感じです。それ以外のルールに関しては、なるべくデータ構造の定義で解決していきたいです。 他にもアクセスするデータのkey名称等を定義して、自動的にそれらにアクセスする方針を考えています。趣旨と違った回答であれば申し訳ないです。
Tak1wa

2015/05/11 10:44

katzC4ISRへの返答を見ました。 単純にJSONを扱いたいのですか? 「データ構造の定義」とは、クラス定義の変更と解釈しても宜しかったでしょうか。 それともクラス定義に手を加えずにJSONの変更に対応したいという意味でしたか。
Tak1wa

2015/05/11 10:45

すみません。「katzC4ISRさん」でした…。 katzC4ISR様、大変失礼致しました。
Tak1wa

2015/05/11 11:02

もし、単純にJSONを扱いたいという要件なのであれば JSONイメージをご提示頂けると助かります。
katzC4ISR

2015/05/11 11:09

いえいえ,お気になさらず.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問