Expand dictionary to JSON fields - c#

We have DTO class like this:
public class DTO
{
public int Number { get; set; }
public string Title { get; set; }
public Dictionary<string, string> CustomFields { get; set; }
}
I want to serialize/deserialize DTO by ServiceStack to JSON where CustomFields is expanded as DTO fields. For example
new DTO
{
Number = 42
Title = "SuperPuper"
CustomFields = new Dictionary<string, string> {{"Description", "HelloWorld"}, {"Color", "Red"}}
}
serialize to
{
"Number":42,
"Title":"SuperPuper",
"Description":"HelloWorld",
"Color":"Red"
}
How can I achieve this?
All dictionary fields must be represented as JSON object fields during serialization.
All fields of incoming JSON object that are not fields of DTO must be put to Dictionary during deserialization.

If you use the Newtonsoft library you can do this:
DTO Test = new DTO
{
Number = 42,
Title = "SuperPuper",
CustomFields = new Dictionary<string, string> { { "Description", "HelloWorld" }, { "Color", "Red" } }
};
String Json = Newtonsoft.Json.JsonConvert.SerializeObject(Test);
Json = Json.Replace("\"CustomFields\":{", "");
Json = Json.Replace("}}", "}");
The resulting json string looks like this:
{"Number":42,"Title":"SuperPuper","Description":"HelloWorld","Color":"Red"}
[Edit]
I'm not going to do ALL your work...this should get you started:
// to reconstruct the object
Newtonsoft.Json.Linq.JObject MyObject = Newtonsoft.Json.JsonConvert.DeserializeObject(Json) as Newtonsoft.Json.Linq.JObject;
// Create a new object here.
foreach( var Token in MyObject)
{
// sample
if (Token.Key == "Number")
{
// populate the fields of the new object with Token.Value
}
}

Related

return custom json response using strongly typed model

My response model class
public class MyModel
{
public Tuple<string, string> Data{ get; set; }
}
var data = new MyModel
{
Data = Tuple.Create("error", "12345");
};
which results in the following json response
{
"data": {
"item1": "error",
"item2": "12345"
}
}
What I want is to create a response as follows
"data" : [{ "error" : "12345" }]
These item1 and item2 are of course dynamic data and it can be anything of type string. I'm saying this because I cannot simply decorate the properties with JsonProperty attribute.
You need either to implement custom serializer for your tuple or change your model to represent the desired structure. If you don't want to create some specific types for your inner data you can leverage Dictionary serialization convention:
public class MyModel
{
public Dictionary<string, string>[] Data{ get; set; }
}
And creation:
var data = new MyModel
{
Data = new[]
{
new Dictionary<string, string> { { "error", "message" } }
}
};
Or make your field into array of objects and create anonymous ones:
public class MyModel
{
public object[] Data{ get; set; }
}
var data = new MyModel
{
Data = new[]
{
new { error = "message" }
}
}

Convert json string from one type to another with .net core c#

I am struggling to convert below input json to output json as this is what is the required format to call
hubspot api to submit a form. I am writing this using .net core within Azure function.
Input Json
{
"Email":"myemail#test.com",
"Phone":"12345678",
"Address":"address 1"
}
Output json
{
"fields": [
{
"name": "Email",
"value": "myemail#test.com"
},
{
"name": "Phone",
"value": "12345678"
},
{
"name": "Address",
"value": "address 1"
}
]
}
I converted the input json to dictionary using
IDictionary<string, string> dictionary = JsonConvert.DeserializeObject<IDictionary<string, string>>(inputJson);
but that gives me key value pair instead of name value pair.
I would like the output as detailed above.
Any help/example code would be highly appreciated.
You could create your own "NameValuePair" class/struct if you don't want "Key" as the field name:
public class FieldContainer
{
[JsonProperty("fields")]
public IEnumerable<NameValuePair> Fields { get; set; }
}
public struct NameValuePair
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
public NameValuePair(string name, string value)
{
Name = name;
Value = value;
}
}
And then do like you've already done, but converting the KeyValuePairs into your own struct:
var inJson = #"{
""Email"":""myemail#test.com"",
""Phone"":""12345678"",
""Address"":""address 1""
}";
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(inJson);
var container = new FieldContainer
{
Fields = dict.Select(pair => new NameValuePair(pair.Key, pair.Value))
};
var outJson = JsonConvert.SerializeObject(container);
See this fiddle for a demonstration.
Easiest way to do this would be to take the json and convert it to Dictionary<string, string>. Loop over each KeyValuePair and create a list of Fields using LINQ. Once you have the List of fields, create your RootObject.
public class RootObject
{
[JsonProperty("fields")]
public List<Field> Fields { get; set; }
}
public class Field
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
// Create a dictionary
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonStr);
// Create a list of Fields
List<Field> fields = dict.Select(x => new Field() { Name = x.Key, Value = x.Value }).ToList();
// Create the final Object.
RootObject rootObj = JsonConvert.SerializeObject(new RootObject() { Fields = fields });
Alternative solution, using JObject.Parse() to parse the original JSON, then iterate its Properties to create an array of JObjects with different names and values.
The resulting IEnumerable<JObject> is then converted to a JArray, used to create the final fields object.
var jObj = JObject.Parse(json);
var newObjects = jObj.Properties().Select(p => new JObject {
new JProperty("name", p.Name),
new JProperty("value", p.Value)});
var fields = new JObject() {
{ "fields", JArray.FromObject(newObjects)}
};
Console.WriteLine(fields);

How do deserialize JSON with non-standard (and varying) property names (in .NET)

I have to read a JSON stream (which I have no control over), which is in the form:
{"files":
{
"/some_file_path.ext": {"size":"1000", "data":"xxx", "data2":"yyy"},
"/other_file_path.ext": {"size":"2000", "data":"xxx", "data2":"yyy"},
"/another_file_path.ext": {"size":"3000", "data":"xxx", "data2":"yyy"},
}
}
So, I have an object named files, which has a number of properties, which have 1) different names every time, 2) different number of them every time, and 3) names with characters which can't be used in C# properties.
How do I deserialize this?
I'm putting this into a Portable Library, so I can't use the JavaScriptSerializer, in System.Web.Script.Serialization, and I'm not sure about JSON.NET. I was hoping to use the standard DataContractJsonSerializer.
UPDATE: I've changed the sample data to be closer to the actual data, and corrected the JSON syntax in the area the wasn't important. (Still simplified quite a bit, but the other parts are fairly standard)
You can model your "files" object as a Dictionary keyed by the JSON property name:
public class RootObject
{
public Dictionary<string, PathData> files { get; set; }
}
public class PathData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
Then, only if you are using .Net 4.5 or later, you can deserialize using DataContractJsonSerializer, but you must first set DataContractJsonSerializerSettings.UseSimpleDictionaryFormat = true:
var settings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true };
var root = DataContractJsonSerializerHelper.GetObject<RootObject>(jsonString, settings);
With the helper method:
public static class DataContractJsonSerializerHelper
{
public static T GetObject<T>(string json, DataContractJsonSerializer serializer = null)
{
using (var stream = GenerateStreamFromString(json))
{
var obj = (serializer ?? new DataContractJsonSerializer(typeof(T))).ReadObject(stream);
return (T)obj;
}
}
public static T GetObject<T>(string json, DataContractJsonSerializerSettings settings)
{
return GetObject<T>(json, new DataContractJsonSerializer(typeof(T), settings));
}
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
}
Alternatively, you can install Json.NET and do:
var root = JsonConvert.DeserializeObject<RootObject>(jsonString);
Json.NET automatically serializes dictionaries to JSON objects without needing to change settings.
We need to first convert this Invalid JSON to a Valid JSON. So a Valid JSON should look like this
{
"files":
{
"FilePath" : "C:\\some\\file\\path",
"FileData" : {
"size": 1000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\other\\file\\path",
"FileData" : {
"size": 2000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\another\\file\\path",
"FileData" : {
"size": 3000,
"data": "xxx",
"data2": "yyy"
}
}
}
To make it a valid JSON we might use some string functions to make it looks like above. Such as
MyJSON = MyJSON.Replace("\\", "\\\\");
MyJSON = MyJSON.Replace("files", "\"files\"");
MyJSON = MyJSON.Replace("data:", "\"data:\"");
MyJSON = MyJSON.Replace("data2", "\"data2\"");
MyJSON = MyJSON.Replace(": {size", ",\"FileData\" : {\"size\"");
MyJSON = MyJSON.Replace("C:", "\"FilePath\" :\"C:");
Than we can create a class like below to read the
public class FileData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
public class Files
{
public string FilePath { get; set; }
public FileData FileData { get; set; }
}
public class RootObject
{
public Files files { get; set; }
}
Assuming you have a valid JSON you could use JavaScriptSerializer to return a list of objects
string json = "{}"
var serializer = new JavaScriptSerializer();
var deserializedValues = (Dictionary<string, object>)serializer.Deserialize(json, typeof(object));
Alternatively you could specify Dictionary<string, List<string>> as the type argument
strign json = "{}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
var deserializedValues = serializer.Deserialize<Dictionary<string, List<string>>>(json);
foreach (KeyValuePair<string, List<string>> kvp in deserializedValues)
{
Console.WriteLine(kvp.Key + ": " + string.Join(",", kvp.Value));
}

JSON.Net Convert inner object to C# Model

I have the following JSON coming back from a remote API (I cannot modify the JSON returned)
{
"APITicket": {
"location": "SOMEVALUE",
"ticket": "SOMEVALUE"
}
}
Now using JSON.Net to convert to this to a model I have to create 2 models.
public class TicketModel
{
public string location { get; set; }
public string ticket { get; set; }
}
public class TicketContainer
{
public TicketModel APITicket { get; set; }
}
and do something like..
var myObject = JsonConvert.DeserializeObject<TicketContainer>(this.JSONResponse);
and this works well - my problem arises when I have around 50 calls to make to the API and really dont fancy creating a second 'Container' for each. Is there a way to bind the example above directly to the TicketModel?
You can do it this way:
var json = #"
{
'APITicket': {
'location': 'SOMEVALUE',
'ticket': 'SOMEVALUE'
}
}";
//Parse the JSON:
var jObject = JObject.Parse(json);
//Select the nested property (we expect only one):
var jProperty = (JProperty)jObject.Children().Single();
//Deserialize it's value to a TicketModel instance:
var ticket = jProperty.Value.ToObject<TicketModel>();
use Newtonsoft's JArray to customize ur json before deserialize
public List<APITicket> JsonParser(string json)
{
Newtonsoft.Json.Linq.JArray jArray = Newtonsoft.Json.Linq.JArray.Parse(json);
var list = new List<APITicket>();
foreach(var item in jArray)
{
list.Add(
new APITicket { location = item["APITicket"]["location"],
ticket = item["APITicket"]["ticket"]
}
);
}
return list;
}
Modify the JSON so it looks like this
{
"location": "SOMEVALUE",
"ticket": "SOMEVALUE"
}
and do
List<TicketModel> tickets = JsonConvert.DeserializeObject<List<TicketModel>>(this.JSONResponse);
or even
Dictionary<string, string> tickets = JsonConvert.DeserializeObject<Dictionary<string, string>>(this.JSONResponse);
so you don't need any models.

Deserialize JSON into string

How can I deserialize:
{
"data": [
{"ForecastID":8587961,"StatusForecast":"Done"},
{"ForecastID":8588095,"StatusForecast":"Done"},
{"ForecastID":8588136,"StatusForecast":"Done"},
{"ForecastID":8588142,"StatusForecast":"Pending"}
]
}
to
class RawData
{
public string data { get; set; }
}
So, I just want to have
[
{"ForecastID":8587961,"StatusForecast":"Done"},
{"ForecastID":8588095,"StatusForecast":"Done"},
{"ForecastID":8588136,"StatusForecast":"Done"},
{"ForecastID":8588142,"StatusForecast":"Pending"}
]
as value of property data of RawData's class instance.
Using Json.Net
var obj = (JObject)JsonConvert.DeserializeObject(json);
var newJson = obj["data"].ToString();
or using built-in JavaScriptSerializer
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
var newjson = new JavaScriptSerializer().Serialize(dict["data"]);
It would have made far much more sense to deserialize this JSON structure to:
public class Forecast
{
public IEnumerable<ForecastData> Data { get; set; }
}
public class ForecastData
{
public int ForecastID { get; set; }
public string StatusForecast { get; set; }
}
which is pretty trivial with the JavaScriptSerializer class that's built into the framework:
string json = "your JSON data here";
IEnumerable<ForecastData> data = new JavaScriptSerializer()
.Deserialize<Forecast>(json)
.Data;
or if you don't want to define models you could do that:
dynamic result = new JavaScriptSerializer().DeserializeObject(json);
foreach (var item in result["data"])
{
Console.WriteLine("{0}: {1}", item["ForecastID"], item["StatusForecast"]);
}

Categories

Resources