Parse database - save info in table as json - c#

I'm using ASP.NET MVC 4 with the Parse database (https://www.parse.com/). I have a table called app and a field called reviews. In this field i want to save a json object with the following format:
[{"Title":"a title", "url":"a url"}, {"Title":"another title", "url":"another url"}, etc...]
As I have read in the documentation (https://www.parse.com/docs/dotnet_guide#objects-types) Parse supports objects that implement IDictionary<string, T> and IList<T> so i have the following code:
var requestFormInformation = new ParseObject("app");
requestFormInformation["Reviews"] = requestForm.Reviews.ToList();
Reviews property is an IEnumerable<Review> and this is the Review class
public class Review
{
public string Title { get; set; }
public string Url { get; set; }
}
There is no error thrown when i save this code and save in the database but the item is not saved.

You might want to place your code into a try-catch (ParseException) to see if the save fails for some reason.
Sidenote: the Parse help page suggests that you start the class name with a uppercase character and the key name with a lowercase character. "app" should be "App" and "Reviews" should be "reviews".
Another thing could be authentication or authorization. Are you properly authenticated and do you have the rights to save this object.

You need to be clear about how you want to save the data. You say you want to save it as JSON, which is a string serialization format, so the column should be of type string, and you'll have to handle JSON serialize/deserialize yourself. I don't think this is what you actually want, so forget about JSON as that is an implementation detail inside Parse.
If instead you want it to just serialize your collection you don't have to do anything special. As per the documentation on object types you can store anything that implements IList or IDictionary including nested objects.
I would suggest you try an experiment with a simple class that has a List as one of its properties:
var foo = new ParseObject("Foo");
var reviews = new List<Review>();
reviews.Add(new Review { Title = "Review 1" });
reviews.Add(new Review { Title = "Review 2" });
foo["reviews"] = reviews;
await foo.SaveAsync();
Once that is working, test incremental changes till you find out where things have gone wrong.

Related

Deserialize JSON with empty attribute name

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""]}")

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:

How to add example values for parameters in Swagger-UI built by Nancy.Swagger package?

I have used Nancy.Swagger package and MetadataModule to build a Swagger UI for my APIs (according to this link: https://github.com/yahehe/Nancy.Swagger/wiki/Nancy.Swagger-for-Nancy-v2).
I get the UI, but the problem is that I cannot add example values for the properties of the object, which is passed as a parameter in body.
I see, for example, this output:
Here, instead of the word "string", I would like to have a real example value. But I don't know how I can add example values in this approach, and I would appreciate any help.
Snippet from the API and the parameter (object of PRequest):
Post("/", async (x, ctx) =>
{
PRequest PostRequestModel;
try
{
postRequestModel = this.Bind<PRequest>();
}
Snippet from MetaDataModule:
Describe["Post"] = desc => desc.AsSwagger(
with => with.Operation(
op => op.OperationId("Post")
.Tag("User")
.Summary("Post a new User")
.Description("This creates a new user.")
.BodyParameter(bp => bp.Description("A PRequest object").Name("PRequest").Schema<PRequest>())
I know it has been absolutely ages since you opened this, but I figured I'd share anyways.
First you need a model, like so:
public class Model
{
public string ExampleString { get; set; }
}
You need to create an instance of this model filled with whatever examples you want.
var exampleModel = new Model() { ExampleString = "foobar" }
Then you can add it to the BodyParameter like so:
.BodyParameter(para => para.Name("Example").Schema(
new Schema() { Example = exampleModel }
).Build())
I just created a public static class to hold all my example objects, then I set them like Example = Examples.Example1. I think this is the most readable approach.
A couple problems exist with this approach that I haven't found a solution to (yet). One is that the Example object does not seem to respect whatever settings you're using for Json serialization. Also, I've been unable to get this working concurrently with the Model view, but the Model view was always mostly useless in my eyes anyway. I'll update this if I ever figure any of these issues out. :)

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.

How to create a composite index in Ravendb

I have documents collection "Messages" in my base (RavenDB)
Document definition like:
class Message
{
string Content;
Tag[] Tags;
Location[] Locations;
string[] Actions;
bool IsActive;
}
Tag class definition:
class Tag
{
string Value;
Translation[] Translations;
}
Location class:
class Location
{
string Code;
Translation[] Translations;
}
Translation class:
class Translation
{
string LanguageCode;
string Value;
}
So, I want to create a index that will allow me to make queries by several fields:
Full-text search by Message.Content
Only messages with IsActive==true
Messages that contains my action in Message.Actions
Messages that contains tag with myValue and myLanguageCode
Locations that contains location with some myCode and myLanguageCode
I would like to query to be on all the conditions simultaneously
So, how should i define index for RavenDB?
Well, after a short studies of RavenDB auto dynamic indexes i created something like
new IndexDefinition
{
Map = #"
from doc in docs.Messages
where IsActive==true
from docActionsItem in (IEnumerable<dynamic>)doc.Actions
from docTagsItem in (IEnumerable<dynamic>)doc.Tags
from docTagsItemTranslationsItem in (IEnumerable<dynamic>)docTagsItem.Translations
from docLocationsItem in (IEnumerable<dynamic>)doc.Locations
from docLocationsItemTranslationsItem in (IEnumerable<dynamic>)docLocationsItem.Translations
select new {
TagsValue = docTagsItem.Value,
Content = doc.Content,
Actions=docActionsItem,
TagsTranslationsLanguageCode = docTagsItemTranslationsItem.LanguageCode,
TagsTranslationsValue = docTagsItemTranslationsItem.Value,
LocationsCode = docLocationsItem.Code,
LocationsTranslationsLanguageCode=docLocationsItemTranslationsItem.LanguageCode,
LocationsTranslationsValue=docLocationsItemTranslationsItem.Value
}",
Analyzers =
{
{"Content", typeof(StandardAnalyzer).FullName},
}
}
There's no need to define an index upfront to do queries in RavenDB. Just create the linq-query - RavenDB will then dynamically create an index for you without any additional cost.
The only use-case where you would possible want to create an index by your own, would be if want do specify a different Lucene.NET analyzer to do what you call "full-text search" on the field Message.Content. But even that should be as simple as just creating the linq-query for the index and pass it into RavenDB on startup. If you want to know how to do that, I recommend to have a look into Ayende RaccoonBlog sample or the officials docs, which will be updated soon (FYI -> ravendb/docs has the new docs).

Categories

Resources