Deserialize JSON with empty attribute name - c#

How can I DeserializeObject the following JSON string to a C# object
{"":["Waybill already exist"]}
In some instances the "" can contain a value as well
Like
{"RecevierAddress1" : ["Receiver address 1 can not be blank]}

Whereas what You ask is not possible in principle, because an object property must have a name, what you can do is convert it to a .net JsonDocument which can have properties of zero length string naming.
I presume RL data cause for you to have to handle this, which of cause indicates poor data quality besides that, but You should be able to process it using this technique, here from a unit test
[Fact]
public void SerializeSillyObjectJsonTest()
{
string serialized = "{\"\":[\"Waybill already exist\"]}";
var jdoc = System.Text.Json.JsonDocument.Parse(serialized);
Assert.NotNull(jdoc);
var jsonElement = jdoc.RootElement.GetProperty("");
Assert.Equal(1, jsonElement.GetArrayLength());
}
So You see you can also check on if your property with said name exist and choose what to look for
jdoc.RootElement.TryGetProperty("RecevierAddress1", out var receiverAddressElement)

You can use JsonProperty("") to set the property name to an empty string
class root
{
[JsonProperty("")]
public string[] x;
}
JsonConvert.DeserializeObject<root>(#"{"""":[""Waybill already exist""]}")
For dynamic names, you can either have two properties, or deserialize to a dictionary
JsonConvert.DeserializeObject<Dictionary<string, string[]>>(#"{"""":[""Waybill already exist""]}")

Related

Anonymous object with key name with hyphen C# [duplicate]

Is it possible to create an object with a property name that contains a dash character?
I am creating an anonymous object so that I can serialize it to Json using Json.Net and one of the properties I need contains a '-' dash character.
An example of what I want is:
var document = {
condtions = new {
acl = "public-read",
bucket = "s3-bucketname",
starts-with = "test/path"
}
};
I know I could replace the dash with underscores when creating the object and then replace them in the serialized string afterwards, but wanted to know if there is a way in the language to do this without this workaround.
You can't do this with anonymous objects; field names must be valid identifiers. You could instead use a Dictionary, which Json.Net should serialise just as easily as an anonymous object:
var document = new {
conditions = new Dictionary<string, string>() {
{ "acl", "public-read" },
{ "bucket", "s3-bucketname" },
{ "starts-with", "test/path" }
}
};
Not in c#, no. However most serializers allow you to customise this - often via attributes. IIRC with JSON.NET you want [JsonProperty("starts-with")] to specify the name. However you can't use attributes on anonymous types, so you may need to define a class with the properties (and attributes) the you desire.
Unfortunately, that's not possible, because the language would not be able to differentiate the two following expressions:
condition.starts-with; // Read "starts-with" property.
condition.starts - with; // Read "starts" property and subtract "with" variable.

Deserializing Json: Custom Fields with Numeric Identifiers

I am working with a vendor who has a Restful API infrastructure that allows for "custom fields" on certain entities. When you create a custom field on one of their entities through their interface, you give the custom entity a name. However, in their API, you try to use that custom field, it is actually specified by an int (which represents a unique ID for that field). For example, the first custom field you create on an entity will have an ID of 1, and that is how you access or read that field from the API.
So in the below Json response sample, you'll see that the custom fields for enrollment are returned in the "enrollment fields" collection. 4 is the ID of the custom field, and ABC123 is the value populated in that custom field.
"enrollment_fields":{
"4":"ABC123"
},
I'm not quite sure how I would handle this in my Object Class. Obviously I can't give an object member a number as a name. How would I go about deserializing this type of member into my object so that I can read the value ABC123?
Since Object in C# can't have property as number, there is two way you can do
If your key is not going to change:
[JsonProperty(PropertyName = "4")]
public String Four { get; set; }
Else, you can use a Dictionary<string, string>.
Here I create a sample console app for your demonstration purpose.
class Program
{
static void Main(string[] args)
{
//This is your sample json that comes from Rest API
string json = #"
{'enrollment_fields':{
'4':'ABC123',
'5': 'XYZ123',
'6': 'PQR123'
}
}";
//Deserialize your json into Dictionary of dictionary.
var obj = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json);
//Get your desired key from outer dictionary
var enrollment_fields = obj["enrollment_fields"];
//Loop on inner dictionary key to get values
foreach (string key in enrollment_fields.Keys)
//Here you get your dynamic key. e.g. 4,5,6
Console.WriteLine(key + ": " + enrollment_fields[key]);
Console.ReadLine();
}
}
Note: Download Newtonsoft.json form Nuget Package Manager and in your program use namespace like using Newtonsoft.Json;.
Output:

Using a Dictionary<string, Type> to use the value as type of a list

I am trying to build a solution fitting with the problem of not knowing what kind of Setting type I am dealing with.
I got a Dictionary<string, Type> (which I initially wanted to make <string, class> but that didn't work)
that I want to fill with the setting code and the type of class attached to it i.e.
{ "person_customField", typeof(CustomFieldModel) }
Why I want to do this is because I have a field in my database filled with json data that should be deserialized to a List<> but I don't know what kind of setting it is until I get the object from the database. I can use the Code field to detemine what type it is (person_CustomField should use the CustomFieldModel class, but emailSetting should use EmailSettingModel to match parameters to.
Is there a way to successfully make this statement work with?
JsonConvert.DeserializeObject<List<SettingTypes[record.SettingCode]>>(record.SettingValues).ToList<ISetting>()
Or should I go a different route
Code Sample:
public static readonly Dictionary<string, Type> SettingTypes = new Dictionary<string, Type>()
{
{ "person_CustomFields", typeof(CustomFieldModel)},
};
public static TenantSettingEdit ConvertToTenantSettingEdit(this T_TenantSetting rec)
{
var test = SettingTypes[rec.TENS_Code];
TenantSettingEdit item = new TenantSettingEdit()
{
IDToken = rec.TENS_TenantSettingID.toVirtualGuid().ToString(),
Code = rec.TENS_Code,
Settings = JsonConvert.DeserializeObject<List<SettingTypes[rec.TENS_Code]>>(rec.TENS_Setting).ToList<ITenantSetting>(),
IsActive = rec.TENS_ActiveRec,
};
return item;
}
(I have done this before with PHP but I am not sure if this is even remotely possible with C#)
Why I want to do this is because I have a field in my database filled
with json data that should be deserialized to a List<> but I don't
know what kind of setting it is until I get the object from the
database.
If you're using Json.Net for JSON serialization/deserialization you can use the TypeNameHandling property to embed Type information in the resulting JSON. That JSON can the be deserialized by Json.Net without additional information. If it is necessary to map custom values to the types instead of the automatically generated ones you can use a SerializationBinder (check out this answer).
If none of those help you, you can still fall back to reflection in the way M Kloster describes.
You cannot use a variable as the type parameter in the code, no. What you need to do is to generate the type-specific method by reflection:
var genericMethod = ((Func<string, int>)Json.DeserializeObject<int>).Method.GetGenericMethodDefinition();
var boundMethod = genericMethod.MakeGenericMethod(SettingTypes[record.SettingCode]);
var result = boundMethod.Invoke(null, rec.TENS_Setting)...

Converting a Javascript JSON.stringfy string to an object using c# JSON.NET

I am developing a windows 8 app, and i have some javascript that stores a serialized object into roaming settings, i.e:
var object = [{"id":1}, {"id":2}]
roamingSettings.values["example"] = JSON.stringify(object);
I also i have a c# part to the application (for running a background task), that needs to read that JSON, and turn it into an object so i can iterate over it. And this is where i am having some issues, i am using JSON.NET to do the work, but every thing i turn turns up with an error:
// this looks like "[{\"id\":1},{\"id\":2}]"
string exampleJSON = roaming.Values["example"].ToString();
// dont know if this is correct:
List<string> example = JsonConvert.DeserializeObject<List<string>>(exampleJSON );
That give an error of:
Error reading string. Unexpected token: StartObject. Path '[0]', line 1, position 2.
So i am at a loss of what to do, i have been working on it for last few hours, and i am quite unfamiliar with c#, so resorting to the help of stackoverflow ;D
Thanks in advance for any help :)
Andy
Json.Net has a nice method DeserializeAnonymousType. No need to declare a temporary class.
string json = "[{\"id\":1},{\"id\":2}]";
var anonymous = new []{new{id=0}};
anonymous = JsonConvert.DeserializeAnonymousType(json,anonymous);
foreach (var item in anonymous)
{
Console.WriteLine(item.id);
}
You can even use the dynamic keyword
dynamic dynObj = JsonConvert.DeserializeObject(json);
foreach (var item in dynObj)
{
Console.WriteLine(item.id);
}
You are trying to parse your JSON array into a List of strings, which doesn't work. The JSON object you provide is actually a list of objects containing an integer property called 'id'.
Perhaps try creating a class (say, MyClass) with just that property, and deserialize into List.
Your json containts a collection of objects with an id property, something like this:
class IdObject {
public int id { get; set; }
}
You could then do:
JsonConvert.DeserializeObject<List<IdObject>>(exampleJSON);
Because the IdObject class has a property id to match your json serialized value, it will be mapped back.

c# get attributes from object

I'm a bit new to C# and I got this script that gets a record from a mssql database. There it converts the key to an object.
Its:
Object obj = result[i];
When I enable a breakpoint on the line after the declaration I see the data that is inside the object. Now I need to access the attribute with the data but because Im a bit new to C# I dont know how to do that.
Lets say the attribute is called: name
I made a new class of my own also with the attribute name.
When I try to get the name of the key to my object with:
myObject.Name = (string) obj.Name;
The IDE already gives an error that the attribute in the obj isnt available.
How can I access the name attribute of the object to get it to my own object?
Thanks!
So result[i] is an instance of your class (which I'll call Foo for convenience)? Then you can say
Foo obj = result[i];
myObject.Name = obj.Name;
or
Object obj = result[i];
myObject.Name = ((Foo)obj).Name;
You need to cast your object to proper type. E.g. if your object is:
class MyObject
{
public string Name { get; set; }
}
than you need to cast it like:
MyObject obj = (MyObject)result[i];
you're trying to access an attribute of the Object class, and it has no attributes. You either have to cast your obj to the class that you created, the one that has the Name attribute, or (more simply), when reading the database read it directly into an instance of your class, something like:
MyClass obj = result[i]
What data is present in result[i]? Is it just a string from a field in the record in the database? (That is, is result a DataRow?) As it stands, you're placing it inside of just an Object which doesn't know much about it. Basically, you're "boxing" it and removing knowledge of the object's data from the compiler.
If result[i] is just a string, try something like:
myObject.Name = System.Convert.ToString(result[i]);
Now, this is fairly beginner in that there are other considerations to be made here. If result[i] is ever null then this will throw an exception, etc. But while you're learning this should get the data you're looking for.

Categories

Resources