Create JSON objects from System.Text.Json

For a while now I've been trying to get away from dependencies that I don't need anymore, including Newtonsoft.Json, however now I have the following issue: How could I create a JSON object like this
{
"key": {
"key2":391648,
"key3": [true, false, true]
}

}
{
"key": {
"key2":391648,
"key3": [true, false, true]
}

}
Usually I would have used JObject but that is no longer an option, so what's the equivalent in System.Text.Json (at best without creating a whole new Object / Class for the model)
69 Replies
leowest
leowest9mo ago
creating models is honestly the simplest route... using JObject can cut corners but are as good as using dynamic and can cause more harm then good. If u copy that JSON on visual studio and then go to Edit > Paste Special > Paste JSON as Classes it will generate all the model for you. Its not always perfect and in most cases u might need to change some types or objects around, but for what u have above it produces:
public class Rootobject
{
public Key key { get; set; }
}

public class Key
{
public int key2 { get; set; }
public bool[] key3 { get; set; }
}
public class Rootobject
{
public Key key { get; set; }
}

public class Key
{
public int key2 { get; set; }
public bool[] key3 { get; set; }
}
Denis
Denis9mo ago
You can use properly named properties in the C# model
leowest
leowest9mo ago
we can change that bool[] to a List<bool> if u feel more comfortable. It could also be written as a Dictionary but due to the nature of your other objects being different types it would not be a good choice yes you can use JsonPropertyName to rename the properies to whatever u want but Since I dont know what the keys would be representing I opted not to
Denis
Denis9mo ago
And either configure the serialization to generate lowercase keys, or by annotating the properties with respective attributes that specify the target JSON name
leowest
leowest9mo ago
but as an example
Denis
Denis9mo ago
Just an FYI
leowest
leowest9mo ago
public class Rootobject
{
[JsonPropertyName("Key")]
public Key EntryPoint { get; set; }
}

public class Key
{
[JsonPropertyName("key2")]
public int Id { get; set; }
[JsonPropertyName("key3")]
public List<bool> State { get; set; }
}
public class Rootobject
{
[JsonPropertyName("Key")]
public Key EntryPoint { get; set; }
}

public class Key
{
[JsonPropertyName("key2")]
public int Id { get; set; }
[JsonPropertyName("key3")]
public List<bool> State { get; set; }
}
This is just an example where u map the json name to however u prefer to name the properties @Fabio from Human Resources let us know if that makes sense
The Fog from Human Resources
My issue with models is that the JSON I work with is very dynamic, sometimes keys aren't even present etc + for libraries with a lot of REST endpoints for example I don't want to have like 200 objects that server as models
leowest
leowest9mo ago
JSON is very forgiven an object not existing on the json doesn't break the model but yeah Dictionary<Dictionary<string, object>> is what really your json is
The Fog from Human Resources
But it might break the API request on badly written backend software
leowest
leowest9mo ago
I mean if u can provide some examples I can show you how u can handle it
The Fog from Human Resources
I don't have examples available at the moment
leowest
leowest9mo ago
STJ have JsonArray, JsonObject, etc but I really think u should avoid those if possible im sure there might be some cases u have very little options but models are things u will make once
The Fog from Human Resources
I mostly just need something to construct a post request For any responses or other JSON things I use Models
leowest
leowest9mo ago
var key = new JsonObject
{
["key"] = new JsonArray
{
["key2"] = 391648,
["key3"] = new JsonArray { true, false, true }
}
};
var key = new JsonObject
{
["key"] = new JsonArray
{
["key2"] = 391648,
["key3"] = new JsonArray { true, false, true }
}
};
Pobiega
Pobiega9mo ago
If you are making a request, I dont see why you wouldnt use a model you own.
leowest
leowest9mo ago
because he says his requests very dynamically generated
Pobiega
Pobiega9mo ago
to the point where all the keys are unknown at compile time?
leowest
leowest9mo ago
to the point he doesn't want to write models for every of them
Pobiega
Pobiega9mo ago
because anything other than that can be solved with models + dictionary<string,T>
leowest
leowest9mo ago
but to me it doesn't make much sense because models you do it once after u done all your models you're settle so I am waiting for him/her to provide some examples so we have a better idea of what he is working with
Pobiega
Pobiega9mo ago
👍
The Fog from Human Resources
here is an example
The Fog from Human Resources
the code is ass but its like a yr old by now so :SCgetoutofmyhead: i think that is one of the best examples i can give IF models can be dynamic like that id gladly use them but i need something i can directly modify
leowest
leowest9mo ago
sorry can you $paste it to the site below I have no means to copy from image to reuse that
MODiX
MODiX9mo ago
If your code is too long, you can post to https://paste.mod.gg/ and copy the link into chat for others to see your shared code!
The Fog from Human Resources
sure thing
Pobiega
Pobiega9mo ago
I'm pretty sure you can model that quite easily tbh
The Fog from Human Resources
BlazeBin - ssahrkmzvphb
A tool for sharing your source code with the world!
The Fog from Human Resources
also yes i know i butchered the exception thing by just throwing another one.
leowest
leowest9mo ago
yeah I dont really see anything really dynamic in there
The Fog from Human Resources
RestClient and RestRequest are part of RestSharp
leowest
leowest9mo ago
all u showed above have proper naming and types
The Fog from Human Resources
if i can make a model make certain keys just not appear i can gladly use models cause sometimes certain keys cant exist with others etc
leowest
leowest9mo ago
I see like what happens if u send an empty color for example does it break
The Fog from Human Resources
i think it will throw Invalid Request on HTTP Code 400 the api used in that example is very sensitive and i want my approach to be "bulletproof"
leowest
leowest9mo ago
k I will try to model this its missing a bit of information but lets see
leowest
leowest9mo ago
u dont happen to have the json counterpart to help visualize it right?
The Fog from Human Resources
you mean an already constructed JSON?
leowest
leowest9mo ago
yeah
The Fog from Human Resources
i can make one brb also i just saw that having imagelist and caption list as 2 seperate lists is stupid when i can make it a Dictionary :SCgetoutofmyhead:
MODiX
MODiX9mo ago
Pobiega
REPL Result: Success
using System.Text.Json;
using System.Text.Json.Serialization;

var x = new TestModel();

var options =
new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
var json = System.Text.Json.JsonSerializer.Serialize(x, options);

Console.WriteLine(json);

public class TestModel
{
public string? TestValue { get; set; }
}
using System.Text.Json;
using System.Text.Json.Serialization;

var x = new TestModel();

var options =
new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
var json = System.Text.Json.JsonSerializer.Serialize(x, options);

Console.WriteLine(json);

public class TestModel
{
public string? TestValue { get; set; }
}
Console Output
{}
{}
Compile: 507.351ms | Execution: 54.468ms | React with ❌ to remove this embed.
Pobiega
Pobiega9mo ago
tada key ignored you can tell the serializer to ignore any key where the value is null
The Fog from Human Resources
interesting is there also a serializer option to space out the JSON? since i also use Model classes for things like my config, id rather have my config.json file to look like this
{
"someKey":"someVal"
}
{
"someKey":"someVal"
}
than
{"someKey":"someVal"}
{"someKey":"someVal"}
Pobiega
Pobiega9mo ago
yep
The Fog from Human Resources
@leowest i think this will do
Pobiega
Pobiega9mo ago
WriteIndented = true
The Fog from Human Resources
thanks ill test out some stuff later but i think the approach you sent here should work models would also make the Medialist stuff easier i think ill see
leowest
leowest9mo ago
what does this give u? an URL? this.client.upload_media(icon, Types.upload_File_Types.Image) also am I crazy you dont do anything with your media u generate it but never add it to data or extensiondata
The Fog from Human Resources
yes client.upload_media returns an URL
leowest
leowest9mo ago
public class EditProfile
{
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; }
[JsonPropertyName("extensions")]
public Extension ExtensionData { get; set; }
[JsonPropertyName("nickname")]
public string? Nickname { get; set; }
[JsonPropertyName("content")]
public string? Content { get; set; }
[JsonPropertyName("icon")]
public string? Icon { get; set; }
}

public class Extension
{
[JsonPropertyName("style")]
public Style Style { get; set; }
}

public class Style
{
[JsonPropertyName("backgroundColor")]
public string? BackgroundColor { get; set; }
[JsonPropertyName("backgroundMediaList")]
public List<string?>? BackgroundImages { get; set; }
[JsonPropertyName("defaultBubbleId")]
public string? BubbleId { get; set;}
}
public class EditProfile
{
[JsonPropertyName("timestamp")]
public long Timestamp { get; set; }
[JsonPropertyName("extensions")]
public Extension ExtensionData { get; set; }
[JsonPropertyName("nickname")]
public string? Nickname { get; set; }
[JsonPropertyName("content")]
public string? Content { get; set; }
[JsonPropertyName("icon")]
public string? Icon { get; set; }
}

public class Extension
{
[JsonPropertyName("style")]
public Style Style { get; set; }
}

public class Style
{
[JsonPropertyName("backgroundColor")]
public string? BackgroundColor { get; set; }
[JsonPropertyName("backgroundMediaList")]
public List<string?>? BackgroundImages { get; set; }
[JsonPropertyName("defaultBubbleId")]
public string? BubbleId { get; set;}
}
I imagine it being so what this I could probably make Style a Dicitionary there but due to different types it contains its not a good idea and BagroundImage also have mixed types like int, etc so string would fit the best there given your API can accept it
The Fog from Human Resources
the array contains the image link, the media type, the image text (like for rendering but it goes unused for anything thats not a post) and something else wouldnt List<dynamic> or List<object> do the trick?
leowest
leowest9mo ago
I mean you're not even including the media at that point just List<string?>? at that point
leowest
leowest9mo ago
you have int, u have null and have urls all mixed unless you can have a Property for the image the only way u can go thru there is using string using dynamic would not benefit u in anyway
The Fog from Human Resources
oki thanks
leowest
leowest9mo ago
but yeah u still need to fine tune the models and see if the json matches but I would say its close to what u need and I will u tell u, that is not even the nastier JSON i've seen there are some json that have 1 object being 2 different things like a list and a unique type for example where u need to write custom converters to check whether its an array or not and redirect it to the right model a model being some weird Union of both types and it populating the right type
The Fog from Human Resources
I'll do some tests later, it'll probably work Will be easier to make changes to anyways
leowest
leowest9mo ago
@Pobiega anything u would change or u think its fine?
Pobiega
Pobiega9mo ago
looks fine at a glance. I'd remove most if not all the JsonPropertyName (JsonDefaults.Web handles the casing), and use records in most places in places where you have "if X is set, Y must not be set" scenarios, create constructors for each of those scenarios
leowest
leowest9mo ago
I usually keep those in case changes occur to property names but fair
Pobiega
Pobiega9mo ago
Thats a valid choice. I just personally dislike the bloat 😄
leowest
leowest9mo ago
mmmm like Style for example? but Style is by default there but its body may not be
Pobiega
Pobiega9mo ago
yeah that one might need some tweaking, depending on exactly that should work must the style prop be there, even if it has no body? etc
leowest
leowest9mo ago
that is what I get from his code
Pobiega
Pobiega9mo ago
well, if backgroundColor and backgroundImage are both null, it wont be added as far as I can tell but I dont know if thats a valid invocation of this method in general, this code doesnt really follow the "dont make invalid states representable" rule
leowest
leowest9mo ago
yeah
Want results from more Discord servers?
Add your server