Probleme mit JSON-Serializing

  • C#
  • .NET 7–8

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von MasterQ.

    Probleme mit JSON-Serializing

    Moin,

    ich versuche mich neuerdings mit Serialization von Objekten und nutze System.Text.Json.Serialization

    C#-Quellcode

    1. var o = new JsonSerializerOptions() { WriteIndented = true, IncludeFields = true };
    2. var s = JsonSerializer.Serialize(Nodes, o);
    3. _logger?.Information(this, s);
    4. var serialize = JsonSerializer.Deserialize<ObservableCollection<TaskNode>>(s, o);


    wobei Nodes vom Typ ObservableCollection<TaskNode> ist und

    C#-Quellcode

    1. public class TaskNode
    2. {
    3. private ProjectsTaskEntity _entity;
    4. public ProjectsTaskEntity Content => _entity;
    5. private ObservableCollection<TaskNode> _subtasks = new();
    6. public ObservableCollection<TaskNode> SubTasks => _subtasks;
    7. public int TaskId => _entity?.TaskId ?? -1;
    8. public string Name => _entity?.Name ?? "N/A";
    9. public int? CategoryId => _entity?.CategoryId;
    10. public int Ordinal => _entity?.Ordinal ?? -1;
    11. public bool Active => _entity?.Active ?? false;
    12. public int? ResourceId => _entity?.ResourceId;
    13. public int StateId => _entity?.StateId ?? 1;
    14. public string? Remark => _entity?.Remark;
    15. public int? ParentId => _entity?.ParentId;
    16. public int? PrecessorId => _entity?.PrecessorId;
    17. public int Priority => _entity?.Priority ?? 0;
    18. public decimal Costs => _entity?.Costs ?? 0;
    19. public DateTime? Start => _entity?.Start;
    20. public DateTime? End => _entity?.End;
    21. public int Progress => _entity?.Progress ?? 0;
    22. public DateTime? Due => _entity?.Due;
    23. public TaskNode(ProjectsTaskEntity e)
    24. {
    25. _entity = e;
    26. }
    27. public static implicit operator TaskNode(ProjectsTaskEntity e) => new(e);
    28. public override string ToString() => Name;
    29. public void Add(TaskNode n) => SubTasks.Add(n);
    30. }


    System.InvalidOperationException: Each parameter in the deserialization constructor on type 'libProject.Classes.TaskNode' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. Fields are only considered when 'JsonSerializerOptions.IncludeFields' is enabled. The match can be case-insensitive.

    War ja klar, dass das nicht gehen wird. Aber warum?


    Eine kurze Erklärung, was ich da falsch mache, wäre nett.

    Gruß

    MQ

    slice schrieb:

    Uhm, wenn ich mich recht erinnere brauchst du ein Konstruktor ohne Parameter.


    Das war schon mal nicht schlecht. Es kommt immerhin keine Fehlermeldung mehr. Allerdings wird nicht wirklich was eingelesen, die Eigenschaften Content (null) und SubNodes (Count=0) bleiben leer.


    Spoiler anzeigen

    C#-Quellcode

    1. [
    2. {
    3. "Content": {
    4. "TaskId": 1,
    5. "Name": "eins",
    6. "CategoryId": 1,
    7. "Ordinal": 1,
    8. "Active": true,
    9. "ResourceId": 1,
    10. "StateId": 1,
    11. "Remark": null,
    12. "ParentId": null,
    13. "PrecessorId": null,
    14. "Priority": 0,
    15. "Costs": null,
    16. "Start": null,
    17. "End": null,
    18. "Progress": 0,
    19. "Due": null,
    20. "Foreground": null,
    21. "Background": null
    22. },
    23. "SubTasks": [
    24. {
    25. "Content": {
    26. "TaskId": 3,
    27. "Name": "erstes Aktuell",
    28. "CategoryId": 1,
    29. "Ordinal": -1,
    30. "Active": false,
    31. "ResourceId": 1,
    32. "StateId": 1,
    33. "Remark": null,
    34. "ParentId": 1,
    35. "PrecessorId": null,
    36. "Priority": 0,
    37. "Costs": null,
    38. "Start": null,
    39. "End": null,
    40. "Progress": 0,
    41. "Due": null,
    42. "Foreground": null,
    43. "Background": null
    44. },
    45. "SubTasks": [
    46. {
    47. "Content": {
    48. "TaskId": 4,
    49. "Name": "zweites Aktuell",
    50. "CategoryId": 1,
    51. "Ordinal": -1,
    52. "Active": false,
    53. "ResourceId": 1,
    54. "StateId": 1,
    55. "Remark": null,
    56. "ParentId": 3,
    57. "PrecessorId": null,
    58. "Priority": 0,
    59. "Costs": null,
    60. "Start": null,
    61. "End": null,
    62. "Progress": 0,
    63. "Due": null,
    64. "Foreground": null,
    65. "Background": null
    66. },
    67. "SubTasks": [],
    68. "TaskId": 4,
    69. "Name": "zweites Aktuell",
    70. "CategoryId": 1,
    71. "Ordinal": -1,
    72. "Active": false,
    73. "ResourceId": 1,
    74. "StateId": 1,
    75. "Remark": null,
    76. "ParentId": 3,
    77. "PrecessorId": null,
    78. "Priority": 0,
    79. "Costs": 0,
    80. "Start": null,
    81. "End": null,
    82. "Progress": 0,
    83. "Due": null
    84. }
    85. ],
    86. "TaskId": 3,
    87. "Name": "erstes Aktuell",
    88. "CategoryId": 1,
    89. "Ordinal": -1,
    90. "Active": false,
    91. "ResourceId": 1,
    92. "StateId": 1,
    93. "Remark": null,
    94. "ParentId": 1,
    95. "PrecessorId": null,
    96. "Priority": 0,
    97. "Costs": 0,
    98. "Start": null,
    99. "End": null,
    100. "Progress": 0,
    101. "Due": null
    102. }
    103. ],
    104. "TaskId": 1,
    105. "Name": "eins",
    106. "CategoryId": 1,
    107. "Ordinal": 1,
    108. "Active": true,
    109. "ResourceId": 1,
    110. "StateId": 1,
    111. "Remark": null,
    112. "ParentId": null,
    113. "PrecessorId": null,
    114. "Priority": 0,
    115. "Costs": 0,
    116. "Start": null,
    117. "End": null,
    118. "Progress": 0,
    119. "Due": null
    120. },
    121. {
    122. "Content": {
    123. "TaskId": 2,
    124. "Name": "zwei",
    125. "CategoryId": 1,
    126. "Ordinal": 2,
    127. "Active": false,
    128. "ResourceId": 1,
    129. "StateId": 1,
    130. "Remark": null,
    131. "ParentId": null,
    132. "PrecessorId": null,
    133. "Priority": 0,
    134. "Costs": null,
    135. "Start": null,
    136. "End": null,
    137. "Progress": 0,
    138. "Due": null,
    139. "Foreground": null,
    140. "Background": null
    141. },
    142. "SubTasks": [],
    143. "TaskId": 2,
    144. "Name": "zwei",
    145. "CategoryId": 1,
    146. "Ordinal": 2,
    147. "Active": false,
    148. "ResourceId": 1,
    149. "StateId": 1,
    150. "Remark": null,
    151. "ParentId": null,
    152. "PrecessorId": null,
    153. "Priority": 0,
    154. "Costs": 0,
    155. "Start": null,
    156. "End": null,
    157. "Progress": 0,
    158. "Due": null
    159. }
    160. ]


    Spoiler anzeigen

    C#-Quellcode

    1. [
    2. {
    3. "Content": null,
    4. "SubTasks": [],
    5. "TaskId": -1,
    6. "Name": "N/A",
    7. "CategoryId": null,
    8. "Ordinal": -1,
    9. "Active": false,
    10. "ResourceId": null,
    11. "StateId": 1,
    12. "Remark": null,
    13. "ParentId": null,
    14. "PrecessorId": null,
    15. "Priority": 0,
    16. "Costs": 0,
    17. "Start": null,
    18. "End": null,
    19. "Progress": 0,
    20. "Due": null
    21. },
    22. {
    23. "Content": null,
    24. "SubTasks": [],
    25. "TaskId": -1,
    26. "Name": "N/A",
    27. "CategoryId": null,
    28. "Ordinal": -1,
    29. "Active": false,
    30. "ResourceId": null,
    31. "StateId": 1,
    32. "Remark": null,
    33. "ParentId": null,
    34. "PrecessorId": null,
    35. "Priority": 0,
    36. "Costs": 0,
    37. "Start": null,
    38. "End": null,
    39. "Progress": 0,
    40. "Due": null
    41. }
    42. ]


    wobei das Datenmodell eigentlich so aussieht, d.h. so landet das auf dem Schirm:



    hmmm, im serialisierten JSON ist irgendwie alles doppelt drin und im deserialisierten gar nix. Immerhin stimmt die Anzahl (2) der Items in der obersten Ebene. Das war's auch schon.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MasterQ“ ()

    Glaub das hängt mit ObservableCollection zusammen, versuch das mal mit ner List.

    Generell würde ich Datenstrukturen vom Rest trennen.
    Bei VB.NET gbts da den Zusatz <Serializable()>
    Den brauche ich immer um meine Struktures zu serialisieren und in eine Datei zu speichern und von dort zu laden.

    VB.NET-Quellcode

    1. <Serializable()>
    2. Structure SmartHomeButtonsStruct
    3. Dim Name As String
    4. Dim IP_HTTPURL As String
    5. End Structure
    6. Public SmartHomeButtons(35) As SmartHomeButtonsStruct


    Ich weiß nicht ob das vielleicht auch in C hilft. Oder bin ich da ganz wo anders?
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    slice schrieb:

    Glaub das hängt mit ObservableCollection zusammen, versuch das mal mit ner List.


    Ich brauche eine ObservableCollection, da nur diese beim Binding angenommen wird. Ich müsste dann erstmal umschaufeln, probier ich morgen.


    Generell würde ich Datenstrukturen vom Rest trennen.

    Wie meinst du das? Der Code den ich gezeigt habe liegt in einer DLL, die dem View im Hauptassembly die strukturierte
    Daten liefert, aus denen dann die grafische Darstellung abgeleitet wird. Die DLL wird im ViewModel aufgerufen.

    Nachdem die Daten von einer DB gelesen und in die Collection eingepflegt wurden, habe ich testweise die Serialisierung eingebaut. Da gehört sie am Ende nicht hin, aber zum Ausprobieren ist's da gut aufgehoben.


    [Serilizable] habe ich bei TaskNode angegeben, ändert aber nichts.


    Never mind, ObservableCollection<T> wird wohl mittlerweile unterstützt - ist schon lange her das ich damit gearbeitet habe.

    Kannst du mir das Konstrukt hier mal erklären?

    C#-Quellcode

    1. private ObservableCollection<TaskNode> _subtasks = new();
    2. public ObservableCollection<TaskNode> SubTasks => _subtasks;


    Warum nicht einfach:

    C#-Quellcode

    1. public ObservableCollection<TaskNode> SubTasks => new();



    Kannst du mal folgendes testen:

    C#-Quellcode

    1. object result = JsonSerializer.Deserialize("[true,false]", typeof(ObservableCollection<bool>))

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „slice“ ()

    Haha, danke EdR das habe ich total übersehen :D
    Genau das ist es, was ich mit "Datenstruktur trennen" meine, einfach Null-Logik drin haben und die meisten Probleme tauchen erst gar nicht auf.

    C#-Quellcode

    1. public class TaskNode
    2. {
    3. //public ProjectsTaskEntity Content { get; set; }
    4. public ObservableCollection<TaskNode>? SubTasks { get; set; }
    5. public int? TaskId { get; set; }
    6. public string? Name { get; set; }
    7. public int? CategoryId { get; set; }
    8. public int? Ordinal { get; set; }
    9. public bool? Active { get; set; }
    10. public int? ResourceId { get; set; }
    11. public int? StateId { get; set; }
    12. public string? Remark { get; set; }
    13. public int? ParentId { get; set; }
    14. public int? PrecessorId { get; set; }
    15. public int? Priority { get; set; }
    16. public decimal? Costs { get; set; }
    17. public DateTime? Start { get; set; }
    18. public DateTime? End { get; set; }
    19. public int? Progress { get; set; }
    20. public DateTime? Due { get; set; }
    21. }
    Bilder
    • works.png

      58,81 kB, 1.077×1.230, 26 mal angesehen

    ErfinderDesRades schrieb:

    wenn ich die klasse angucke, ist ja alles abhängig von dem _entity-Dingens, und dassis privat, und ob serialisierbar weiss auch keiner.
    Und die Properties sind alle Readonly - wie soll ein Serializer da Daten eintragen?


    Ja, das kam mir dann auch in den Sinn.

    Nur zu blöd, wenn man zu blöd ist. :whistling:

    --EDIT:
    Kaum macht man's richtig, schon funktioniert's. Ich habe den Vorschlag von slice umgesetzt. An SubTasks musste ich noch ein new() anhängen, dann hat's geklappt.


    Danke


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MasterQ“ ()