C
C#2y ago
Jochem

❔ HTTP request object creation / ignoring fields when deserializing JSON

Hey there. I am writing a program using the Deck of Cards API which can be found here: https://deckofcardsapi.com/. The API returns a response which contains JSON.
class Deck
{
public Deck() { ... }
public Card DrawCard() { ... }
}
class Deck
{
public Deck() { ... }
public Card DrawCard() { ... }
}
I have a class named "Deck", I first wanted "Deck" to load and deserialize itself in the constructor using the API but I don't really know if that's possible or a good idea. I am wondering if there are better alternatives or best practices for this problem.
class Card
{
public string Value;
public string Suit;
public string Image;
}
class Card
{
public string Value;
public string Suit;
public string Image;
}
I also have a second problem. Whenever I want to request a card using the API, the response contains many properties I don't need. Is there a way of only deserializing certain properties? Above you can see a class called "Card" and I only need "Value", "Suit", and "Image" but the JSON in the response contains much more as you can see below. Response when drawing card(s).
{
"success": true,
"deck_id": "kxozasf3edqu",
"cards": [
{
"code": "6H",
"image": "https://deckofcardsapi.com/static/img/6H.png",
"images": {
"svg": "https://deckofcardsapi.com/static/img/6H.svg",
"png": "https://deckofcardsapi.com/static/img/6H.png"
},
"value": "6",
"suit": "HEARTS"
},
{
"code": "5S",
"image": "https://deckofcardsapi.com/static/img/5S.png",
"images": {
"svg": "https://deckofcardsapi.com/static/img/5S.svg",
"png": "https://deckofcardsapi.com/static/img/5S.png"
},
"value": "5",
"suit": "SPADES"
}
],
"remaining": 50
}
{
"success": true,
"deck_id": "kxozasf3edqu",
"cards": [
{
"code": "6H",
"image": "https://deckofcardsapi.com/static/img/6H.png",
"images": {
"svg": "https://deckofcardsapi.com/static/img/6H.svg",
"png": "https://deckofcardsapi.com/static/img/6H.png"
},
"value": "6",
"suit": "HEARTS"
},
{
"code": "5S",
"image": "https://deckofcardsapi.com/static/img/5S.png",
"images": {
"svg": "https://deckofcardsapi.com/static/img/5S.svg",
"png": "https://deckofcardsapi.com/static/img/5S.png"
},
"value": "5",
"suit": "SPADES"
}
],
"remaining": 50
}
Deck of Cards
Deck of Cards - an API for playing cards.
24 Replies
Angius
Angius2y ago
Regarding the first question, constructors cannot be asynchronous, and HTTP calls should be
Angius
Angius2y ago
The usual way would be having some DeckService class that has an async Task<Deck> GetDeck() method For the latter, if the class you deserialize into has only selected properties... it will have only those
Jochem
JochemOP2y ago
Okay thank you both for the responses!
cap5lut
cap5lut2y ago
generally i would say u need a bit more, the suit should be an enum, not a string, afaik stj can automatically translate strings to enums, but if not u might need a little custom converter for that enum
Angius
Angius2y ago
STJ should be able to convert strings to enums, yeah
cap5lut
cap5lut2y ago
never touched it myself for enums so i want sure ;p i rarely use json nowadays but binary (de)serialization using source generates
Jochem
JochemOP2y ago
Yes, I read about custom converters but didn't know it could do that automatically? does it work when the enum name is not case-sensitive equal to the json value?
MODiX
MODiX2y ago
angius#0000
REPL Result: Failure
enum Letters { A, B, C }
record Foo(Letters thing);
System.Text.Json.JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""")
enum Letters { A, B, C }
record Foo(Letters thing);
System.Text.Json.JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""")
Exception: JsonException
- The JSON value could not be converted to Submission#0+Foo. Path: $.thing | LineNumber: 1 | BytePositionInLine: 14.
- The JSON value could not be converted to Submission#0+Foo. Path: $.thing | LineNumber: 1 | BytePositionInLine: 14.
Compile: 605.900ms | Execution: 84.837ms | React with ❌ to remove this embed.
Angius
Angius2y ago
Doesn't work by default, alas
MODiX
MODiX2y ago
angius#0000
REPL Result: Failure
using System.Text.Json;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""")
using System.Text.Json;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""")
Exception: CompilationErrorException
- The type or namespace name 'JsonStringEnumConverter' could not be found (are you missing a using directive or an assembly reference?)
- The type or namespace name 'JsonStringEnumConverter' could not be found (are you missing a using directive or an assembly reference?)
Compile: 681.999ms | Execution: 0.000ms | React with ❌ to remove this embed.
Angius
Angius2y ago
Huh, thought it's an existing converter?
cap5lut
cap5lut2y ago
i think in this case u would even want a custom serializer if i understand it correctly, cuz in ur enum u would use the singular
public enum Suits
{
Heart,
Club,
Spade,
blah
}
public enum Suits
{
Heart,
Club,
Spade,
blah
}
(cant remenber the other one in english :'D) but the api spits it out as plurar (hearts, clubs, spades, blahs)
MODiX
MODiX2y ago
cap5lut#0000
REPL Result: Failure
using System.Text.Json;
using System.Text.Json.Serialization;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""")
using System.Text.Json;
using System.Text.Json.Serialization;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""")
Exception: JsonException
- The JSON value could not be converted to Submission#0+Foo. Path: $.thing | LineNumber: 1 | BytePositionInLine: 14.
- The JSON value could not be converted to Submission#0+Foo. Path: $.thing | LineNumber: 1 | BytePositionInLine: 14.
Compile: 689.527ms | Execution: 103.512ms | React with ❌ to remove this embed.
cap5lut
cap5lut2y ago
hmm ._. we dont pass the options xD
MODiX
MODiX2y ago
cap5lut#0000
REPL Result: Success
using System.Text.Json;
using System.Text.Json.Serialization;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""", options)
using System.Text.Json;
using System.Text.Json.Serialization;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""", options)
Result: Foo
{
"thing": 0
}
{
"thing": 0
}
Compile: 719.373ms | Execution: 95.137ms | React with ❌ to remove this embed.
Angius
Angius2y ago
lmao Yeah, it'll work now
Pobiega
Pobiega2y ago
it is, but iirc its in a different namespace
cap5lut
cap5lut2y ago
yep using System.Text.Json.Serialization;
Pobiega
Pobiega2y ago
as above 😄
MODiX
MODiX2y ago
angius#0000
REPL Result: Success
using System.Text.Json;
using System.Text.Json.Serialization;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

var res = JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""", options);

res is { thing: Letters.A }
using System.Text.Json;
using System.Text.Json.Serialization;

enum Letters { A, B, C }
record Foo(Letters thing);

JsonSerializerOptions options = new JsonSerializerOptions{
Converters ={
new JsonStringEnumConverter()
}
};

var res = JsonSerializer.Deserialize<Foo>("""
{
"thing": "A"
}
""", options);

res is { thing: Letters.A }
Result: bool
True
True
Compile: 735.518ms | Execution: 107.051ms | React with ❌ to remove this embed.
Angius
Angius2y ago
Yeah, deserializes to an enum just fine
cap5lut
cap5lut2y ago
that will probably still apply, or am i wrong here? oh wait wrong referenced message this one ⤴️
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server