🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

3回答

23357閲覧

c# JSONのデシリアライズで変換できないエラーが出ます。

GattoNero

総合スコア26

C#

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

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2021/01/17 00:17

編集2021/01/17 04:59

前提・実現したいこと

JSONをデシリアライズし、JSON中の
faceIdをstringとして。
top,left,width,heightの値をinteger値として取得したいのですが、
'The JSON value could not be converted to FaceFormAPP.FaceDetect. Path: $ | LineNumber: 0 | BytePositionInLine: 1.'
のエラーが出ます。
c#初心者で対応が判らず困っています。宜しくご教授ください。

発生している問題・エラーメッセージ

System.Text.Json.JsonException:

1 場所 System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType) 2 場所 System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) 3 場所 System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) 4 場所 System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) 5 場所 System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state) 6 場所 System.Text.Json.JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, Type returnType, JsonSerializerOptions options) 7 場所 System.Text.Json.JsonSerializer.Deserialize[TValue](String json, Type returnType, JsonSerializerOptions options) 8 場所 System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options) 9 場所 FaceFormAPP.Form1.<MakeAnalysisRequest>d__19.MoveNext() 場所 C:\Azure\FaceForm4+WebCam\FaceFormAPP\Form1.cs:行 186error 10 11```デシリアライズしたいJSONは、

[
{
"faceId":"19f3245b-b8f2-4b4f-89f5-ca",
"faceRectangle":{"top":121,"left":199,"width":190,"height":190},
"recognitionModel":"recognition_03"
}
]

### 該当のクラス宣言コード

public class FaceDetect
{
public string faceId { get; set; }
public FaceRectangle faceRectangle { get; set; }
public string recognitionModel { get; set; }
}
public class FaceRectangle
{
public int top { get; set; }
public int left { get; set; }
public int width { get; set; }
public int height { get; set; }
}

### エラーが発生するコード

//JSONから配列へDesiliarize
FaceDetect FaceDetectRead = new FaceDetect();
//json変数には、デシリアライズしたいJSON文が代入されています。
FaceDetectRead = JsonSerializer.Deserialize<FaceDetect>(json);

###ここに言語名を入力 c# visual studio ### 試したこと 何しろ、c#初めて1週間なので、よろしくお願いいたします。 ### 補足情報(FW/ツールのバージョンなど) Windows10 Visual studio using System.Text.Json;

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/01/17 01:46

開発環境を書いてください。少なくとも使っているデシリアライザが何かぐらいは書きましょう。 JSON やコードは ``` と ``` で囲ってください(``` はバッククォート 3 つ)。インデントされて見やすくなりますので。
GattoNero

2021/01/17 03:29

ご指摘のデシリアライザというのは、ここの宣言?部分の事でしょうか? using System.Text.Json; c#初めて1週間なので、良く分かっていなくて申し訳ありません。
退会済みユーザー

退会済みユーザー

2021/01/17 04:23 編集

> ご指摘のデシリアライザというのは、ここの宣言?部分の事でしょうか? > using System.Text.Json; System.Text.Json は名前空間名です。それでググるとヒットする記事 https://docs.microsoft.com/ja-jp/dotnet/api/system.text.json?view=net-5.0 を読んでもらうと分かると思いますが、.NET Core 用に提供されているものです。 .NET で使われている JSON シリアライザ/デシリアライザは数々あって、質問の最初でそれをはっきりさせないと話が始まらないのです。 今回は質問に書いてあった JsonSerializer.Deserialize から System.Text.Json 名前空間にある .NET Core 用のものだろうとは想像しましたが、想像が外れていると回答も的外れになって混乱を招くばかりです。 なので次回質問する際は必ず開発環境を書くようお願いします。
退会済みユーザー

退会済みユーザー

2021/01/17 04:27

上でお願いした「JSON やコードは ``` と ``` で囲ってください(``` はバッククォート 3 つ)」の件、今からでも遅くないのでやってください。 ここは https://teratail.com/help/question-tips によると、「質問と回答を通してお互いに知識や情報を交換・共有する場所」とのことですので、後から検索などでここを訪れた人にも見やすくなるような配慮をお願いします。
GattoNero

2021/01/17 05:00

コード部分修正いたしました。
退会済みユーザー

退会済みユーザー

2021/01/17 06:22

対応いただきありがとうございました。
guest

回答3

0

他の方の回答とダブるところがありますが、プラスアルファも書いたのでご容赦を・・・

Visual Studio の機能を使って JSON 文字列からクラス定義を生成できます。詳しくは以下の記事を見てください。

JSON 文字列から C# のクラス定義生成
http://surferonwww.info/BlogEngine/post/2020/05/10/generate-class-definition-from-json-string.aspx

それを使うと質問の JSON 文字列、

[ { "faceId":"19f3245b-b8f2-4b4f-89f5-ca21c5b9699c", "faceRectangle":{"top":121,"left":199,"width":190,"height":190}, "recognitionModel":"recognition_03" } ]

から以下のクラス定義が生成できます。これは Rootobject クラスの定義の有無以外は質問にあるものとほぼ同じですね。

public class Rootobject { public Class1[] Property1 { get; set; } } public class Class1 { public string faceId { get; set; } public Facerectangle faceRectangle { get; set; } public string recognitionModel { get; set; } } public class Facerectangle { public int top { get; set; } public int left { get; set; } public int width { get; set; } public int height { get; set; } }

デシリアライザは .NET Core の System.Text.Json 名前空間にある JsonSerializer クラスを使っていると理解していますが、上の JSON 文字列を直接デシリアライズする場合は、

JsonSerializer.Deserialize<Rootobject>(jsonString);

のようにすると JsonException がスローされます。("The JSON value could not be converted to ConsoleApp1.Rootobject." というエラーメッセージになる・・・Newtonsoft.Json のものより分かり難い)

以下のようにする必要があります。Class1[] は List<Class1> でも可です。

JsonSerializer.Deserialize<Class1[]>(jsonString);

ちなみに、

JsonSerializer.Deserialize<Rootobject>(jsonString);

でデシリアライズできるのは、

{"Property1": 質問の JSON 文字列 }

です。以下の画像を見てください。

イメージ説明

なお、本題とは関係ない話ですが、Newtonsoft.Json と違って .NET Core の System.Text.Json.JsonSerializer でデシリアライズする場合、JSON 文字列のキー名とクラス定義のプロパティ名はデフォルトで大文字小文字の区別をするので注意してください。

投稿2021/01/17 02:45

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

GattoNero

2021/01/17 03:24

ご丁寧な解説をありがとうございます。 JSONからクラス宣言を作る部分は、 https://json2csharp.com/ で作ってました。 Visual Studioでも出来るんですね!ありがとうございます。 >JSON 文字列のキー名とクラス定義のプロパティ名はデフォルトで大文字小文字の区別をするので注意してください。 同じプロジェクト内の別なJSONを配列化するルーチンで、これにはまってました。 c#は奥が深いというか、難しいです。
退会済みユーザー

退会済みユーザー

2021/01/17 04:38 編集

先頭が小文字の camel casing を使っているそうです(camelCase というような感じ)。なので、JSON 文字列にシリアライズするときはクラスのプロパティ名が CamelCase でも JSON の文字列の {"name";"value"} の name は camelCase になります。デシリアライズするときクラスのプロパティも camelCase とする必要があります。あくまでデフォルトで、それを変える手段は用意されています。 一方、.NET Framework ベース(Core ではない)のアプリで使われている Newtonsoft.Json のシリアライザ/デシリアライザはそのあたりは違います。なので、開発環境を書くようにとお願いしたのです。
guest

0

ベストアンサー

FaceDetectに相当するデータがひとつだけなのに、取得するJSONが[]で囲まれる(配列である)ことを避けられないなら、他の回答者の方も述べられているように、リストとしてデシリアライズして、先頭の要素だけを[0]で取得すればいいでしょう(using System.Collections.Generic;が必要)。

C#

1var faceDetectRead = JsonSerializer.Deserialize<List<FaceDetect>>(json)[0];

もし、(JSON生成側もあなたが作成しているなどの理由で)取得するJSONから[]を取り除けるのであれば、そのままFaceDetectを指定してデシリアライズできます。なお、あらかじめnew FaceDetect()しておく必要は無いので、デシリアライズしたデータをそのまま変数に代入してください。

C#

1var FaceDetectRead = JsonSerializer.Deserialize<FaceDetect>(json);

投稿2021/01/17 02:04

Daregada

総合スコア11990

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

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

GattoNero

2021/01/17 02:37

早速のアドバイスありがとうございます。 希望通りの動作で、顔画像に四角形を描画出来ました。ありがとうございます。 JSONは、Microsoft Azureから返って来るので[]で囲まれるのは避けられません。 なお、try文の中でデシリアライズしようとしたら、try文の前でnew宣言しないとエラーが出たので、 下記のように修正しました。 // 実行結果からJSONの取得 string contentString = await response.Content.ReadAsStringAsync(); // JSONの出力 textBox1.Text = JsonPrettyPrint(contentString); //変数宣言 これをしないとtry文でエラーが出る FaceDetect FaceDetectRead = new FaceDetect(); try { FaceDetectRead = JsonSerializer.Deserialize<List<FaceDetect>>(contentString)[0]; } catch (Exception e) { textBox15.Text = e + "error"; //throw; } //faceIdを求める textBox1.Text = FaceDetectRead.faceId; //top座標を求める int Top1 = FaceDetectRead.faceRectangle.top; //left座標を求める int Left1=FaceDetectRead.faceRectangle.left; //width座標を求める int Width1 = FaceDetectRead.faceRectangle.width; //height座標を求める int Height1 = FaceDetectRead.faceRectangle.height;
Daregada

2021/01/17 02:44

その場合でも、tryの前に書くのは「FaceDetectRead faceDetectRead;」という変数宣言だけでいいのです。あと、変数名の先頭は小文字で書きましょう。 「= new FaceDetect()」の部分は、オブジェクトを生成して変数に代入しています。このオブジェクトは、一度も使われることなくゴミになります。tryの中でデシリアライズされた別のオブジェクトがfaceDetectReadに代入されるからです。
guest

0

入力のJSONが[]で囲まれている為、全体のデータが配列となっています。
なので、FaceDetectへデシリアライズするのではなくList<FaceDetect>へデシリアライズしてください。

投稿2021/01/17 01:07

YAmaGNZ

総合スコア10469

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

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

GattoNero

2021/01/17 02:40

早速のアドバイスありがとうございます。 FaceDetectRead = JsonSerializer.Deserialize<List<FaceDetect>>(contentString); だと、エラーが出て、 FaceDetectRead = JsonSerializer.Deserialize<List<FaceDetect>>(contentString)[0]; にしたら、OKになりました。 c#は、全くの初心者なので、今後ともよろしくお願いいたします。
YAmaGNZ

2021/01/17 05:07

FaceDetectReadがFaceDetectで宣言されているからエラーとなります。 顔検出人数が増えた場合のJSONが [ { "faceId":"19f3245b-b8f2-4b4f-89f5-ca21c5b9699c", "faceRectangle":{"top":121,"left":199,"width":190,"height":190}, "recognitionModel":"recognition_03" }, { "faceId":"19f3245b-b8f2-4b4f-89f5-ca21c5b9699c", "faceRectangle":{"top":121,"left":199,"width":190,"height":190}, "recognitionModel":"recognition_02" } ] といった感じで返されるのではないかと思いますので、1つ目のデータと決め打ちするのではなく List<FaceDetect> FaceDetectReads; FaceDetectReads = JsonSerializer.Deserialize<List<FaceDetect>>(contentString); としたほうがいいかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問