How to deserialize JSON file into List<T> c# - c#

I can't deserialize JSON file wich contain multiple objects of type Account. Here is how I build my data.json file. I have a List of Accounts List<Account> which is serialize as usual. I separate each object in json file by adding a new line.
List<Account> listOfAccounts = new List<Account>();
if (listOfAccounts != null)
{
foreach (var item in listOfAccounts)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
string outputJSON = ser.Serialize(item);
// I added Environmetn.NewLine to separate each account in json file.
File.AppendAllText("data.json", outputJSON + Environment.NewLine);
}
}
Now, when I'm trying to retrieve all Accounts from the JSON file to List<Account> I get an error: System.ArgumentException: 'Invalid JSON primitive:
Please help to find the solutin, so I can get all objects from the JSON file.
private void JsonFileLoad()
{
if(File.Exists("data.json"))
{
String JSONtxt = File.ReadAllText("data.json");
JavaScriptSerializer ser = new JavaScriptSerializer();
// Not sure how to deserialize all lines into List<account>
List<Account> desirializedAccounts = ser.Deserialize<List<Account>>(JSONtxt);
}
}
I really appreciate any help you can provide.

First of all, you should be serializing in standard json format. What you are doing is serializing the object and writing to file. It should have been, serialize the list altogether to json format.
But assuming you might be having specific reason, I have given many possible solutions in different scenarios.
Note: I have used Newtonsoft.Json as this is fast and I find it very easy.
http://www.newtonsoft.com/json
https://www.nuget.org/packages/newtonsoft.json/
Solutions:
//Class for testing object
public class Account
{
public int Id { get; set; }
public string Name { get; set; }
}
Solution 1: Recommended
/// <summary>
/// Serializing the list in single go
/// </summary>
public void Serialize()
{
List<Account> listOfAccounts = new List<Account>();
listOfAccounts.Add(new Account { Id = 1, Name = "First" });
listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
listOfAccounts.Add(new Account { Id = 3, Name = "Third" });
string outputJSON = Newtonsoft.Json.JsonConvert.SerializeObject(listOfAccounts, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(#"c:\temp\data.json", outputJSON + Environment.NewLine);
}
/// <summary>
/// Serializing the list, one by one object
/// Comma is appended to every object in json format
/// Finally, enclosed it with [ and ] to make it array of objects
/// </summary>
public void Serialize2()
{
List<Account> listOfAccounts = new List<Account>();
listOfAccounts.Add(new Account { Id = 1, Name = "First" });
listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
listOfAccounts.Add(new Account { Id = 3, Name = "Third" });
string outputJSON = "";
foreach(var item in listOfAccounts)
{
outputJSON += Newtonsoft.Json.JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented)+",";
}
File.WriteAllText(#"c:\temp\data.json", "["+outputJSON + "]");
}
/// <summary>
/// Read serialized data into list of objects
/// </summary>
public void DeSerialize()
{
if (File.Exists(#"c:\temp\data.json"))
{
String JSONtxt = File.ReadAllText(#"c:\temp\data.json");
var accounts = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<Account>>(JSONtxt);
}
}
Solution 2: as per your requirement
/// <summary>
/// Non standard json serialization (object one by one) Highly discouraged unless you have specific reason
/// Assuming the output will not have internal objects
/// </summary>
public void SerializeNonStandard()
{
List<Account> listOfAccounts = new List<Account>();
listOfAccounts.Add(new Account { Id = 1, Name = "First" });
listOfAccounts.Add(new Account { Id = 2, Name = "Second" });
listOfAccounts.Add(new Account { Id = 3, Name = "Third" });
foreach (var item in listOfAccounts)
{
string outputJSON = Newtonsoft.Json.JsonConvert.SerializeObject(item, Newtonsoft.Json.Formatting.Indented);
File.AppendAllText(#"c:\temp\data-ns.json", outputJSON + Environment.NewLine);
}
}
/// <summary>
/// Deserializes the list in one by one fashion and appends to list
/// </summary>
public void DeSerializeNonStandard()
{
if (File.Exists(#"c:\temp\data-ns.json"))
{
List<Account> listOfAccounts = new List<Account>();
String JSONtxt = File.ReadAllText(#"c:\temp\data-ns.json");
//Capture JSON string for each object, including curly brackets
Regex regex = new Regex(#".*(?<=\{)[^}]*(?=\}).*", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(JSONtxt);
foreach(Match match in matches)
{
string objStr = match.ToString();
Account account = Newtonsoft.Json.JsonConvert.DeserializeObject<Account>(objStr);
listOfAccounts.Add(account);
}
}
}
/// <summary>
/// Deserializes the non standard json to list of accounts
/// Splits the object strings, merges with comma and encloses with [] to make it array of objects format and deserializes
/// </summary>
public void DeSerializeNonStandardList()
{
if (File.Exists(#"c:\temp\data-ns.json"))
{
String JSONtxt = File.ReadAllText(#"c:\temp\data-ns.json");
//Capture JSON string for each object, including curly brackets
Regex regex = new Regex(#".*(?<=\{)[^}]*(?=\}).*", RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(JSONtxt);
string joinedJSON = string.Join(",", matches.Cast<Match>().Select(m => m.Value));
joinedJSON = string.Format("[{0}]", joinedJSON);
var listOfAccounts = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<Account>>(joinedJSON);
}
}

You are serializing Account and not List of Account that's why deserialize it failed. Do you need to separate those account in new line? if so you could try add char '[' in the 1st and last char ']' in data.json.

Related

How to write strings and bool to a text file (comma separated)

I am trying to make a winform application. The app has 2 textboxes (firstName, lastName), a numericUpDown, and a checkbox. The app is able to read from a text file, with comma separated rows (Daniel,Brown,26,true). The app put this info in a listbox. Then you can add a new user. When you are finished adding users you press save and the new info from lisbox will be saved in that text file. I've created the read file script and add user succesfully. However I can't create the save user button so that it'll save: Daniel,Brown,26,true. I was able to save as: Daniel,Brown,26,happy.
Here is the Person Class:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Age { get; set; }
public bool IsHappy { get; set; }
public override string ToString()
{
var statusText = IsHappy ? "happy" : "not happy";
return $"{FirstName} {LastName} is {Age} and is {statusText}";
}
}
Here is the form.cs with it's script:
public partial class ChallengeForm : Form
{
private BindingList<Person> _persons = new BindingList<Person>();
private PersonsService _personsService;
public ChallengeForm()
{
_personsService = new PersonsService();
InitializeComponent();
WireUpDropDown();
}
private void WireUpDropDown()
{
_persons = new BindingList<Person>(_personsService.GetPersons(#"C:\Users\user\Desktop\Document.TXT"));
usersListBox.DataSource = _persons;
}
private void addUserButton_Click(object sender, EventArgs e)
{
var person = new Person { FirstName = firstNameText.Text, LastName = lastNameText.Text, Age = agePicker.Text, IsHappy = isHappyCheckbox.Checked };
_persons.Add(person);
}
private void saveListButton_Click(object sender, EventArgs e)
{
}
}
My question is how can I convert the status back to bool. And write the listbox to the text file as csv. I would be very thankfull if you could use SoC.
Here is what I've tried:
const string sPath = (#"C:\Users\user\Desktop\Document.TXT");
System.IO.StreamWriter SaveFile = new System.IO.StreamWriter(sPath);
SaveFile.Write(myperson);
foreach (var item in usersListBox.Items)
{
List<string> unwantedWords = new List<string> { "is", "and" };
var linesSplitted = item.ToString().Split(' ').ToList();
var wordsWithoutUnwantedWords = linesSplitted.Where(i => !unwantedWords.Contains(i)).ToList();
for (int i = 0; i<wordsWithoutUnwantedWords.Count; i++)
{
var isLastWord = i == wordsWithoutUnwantedWords.Count - 1;
SaveFile.Write(wordsWithoutUnwantedWords[i]);
if (!isLastWord)
{
SaveFile.Write(",");
}
Look into XML Serialization. You can just pass in your filepath and the object and the rest will be done for you by the Serialisation classes. Code below:
This is taken from DeadlyDog's awesome answer: https://stackoverflow.com/a/22417240/1623971
/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
TextWriter writer = null;
try
{
var serializer = new XmlSerializer(typeof(T));
writer = new StreamWriter(filePath, append);
serializer.Serialize(writer, objectToWrite);
}
finally
{
if (writer != null)
writer.Close();
}
}
/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
TextReader reader = null;
try
{
var serializer = new XmlSerializer(typeof(T));
reader = new StreamReader(filePath);
return (T)serializer.Deserialize(reader);
}
finally
{
if (reader != null)
reader.Close();
}
}
Sample use case:
WriteToXmlFile<Person>("C:\someClass.txt", objectToSerialize);
// Read the file contents back into a variable.
Person deserializedObject = ReadFromXmlFile<Person>("C:\someClass.txt");

How to read in all the data with a certain tag in an XML file using c#?

I am creating a Windows service for checking the integrity of software being installed on a system by creating an MD5 hash for the software being installed and comparing it with the MD5 hashes of verified software. The verified hashes are contained in an XML file that looks like this:
<AppList>
<VLC>
<Path>C:Program Files\VLC\VLC.exe</Path>
<MD5GoldenHash> 1f74882b7a5c8a6ca38912df9786c1cc</MD5GoldenHash>
</VLC>
…
</AppList>
How do I read in all the data with the MD5GoldenHash tag in c# so that I can compare the MD5 hash of the software being installed with the already verified hashes? Any help or tips would be much appreciated.
Use my answer here to create a C# class that represent your XML.
Use the XmlSerializer to deserialize the contents of the XML file.
Do whatever you want to do with the deserialized stuff.
Here are the classes step 1 will generate for you:
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class AppList
{
private AppListVLC[] vLCField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("VLC")]
public AppListVLC[] VLC
{
get
{
return this.vLCField;
}
set
{
this.vLCField = value;
}
}
}
/// <remarks/>
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class AppListVLC
{
private string pathField;
private string mD5GoldenHashField;
/// <remarks/>
public string Path
{
get
{
return this.pathField;
}
set
{
this.pathField = value;
}
}
/// <remarks/>
public string MD5GoldenHash
{
get
{
return this.mD5GoldenHashField;
}
set
{
this.mD5GoldenHashField = value;
}
}
}
And here is how to serialize and deserialize:
public static void Main()
{
var serializer = new XmlSerializer(typeof(AppList));
var reader = new StreamReader("YourFile.xml");
var result = serializer.Deserialize(reader) as AppList;
reader.Close();
foreach (var thisVlc in result.VLC)
{
Console.WriteLine(thisVlc.MD5GoldenHash);
}
// if you want to make changes to xml file then do the following
result.VLC[0].MD5GoldenHash = "Something to show modificaition";
serializer.Serialize(new StreamWriter("YourFileOrSomeOtherFile.xml"), result);
}
I figured out I could read in the data for the specific tag and put it in a list like this:
private List<string> getGoldenHashes(string xml)
{
List<string> list = new List<string>();
int i = 0;
XDocument doc = XDocument.Load(xml);
var goldHashes = doc.Descendants("MD5GoldenHash");
foreach (var gh in goldHashes)
{
list.Add(gh.Value.ToString());
}
return list;
}

Deserialize JSON data with double quote using JavaScriptSerializer.Deserialize

Below JSON data i'm trying to deserialize using JavaScriptSerializer.Deserialize but, am getting below exception.
Code:
var jsonSerialiser = new JavaScriptSerializer();
FCMCasepackVM casepack = jsonSerialiser.Deserialize<FCMCasepackVM>(selectedCasePack);
JSON Data:
{ P_ID:"1478952", P_NM:"BAHLSEN COOKIES WAFER ROLL MILK CHOCOLATE 3.5
OZ", BYR_ID:191, BYR_NM:"BYR_NM", VDR_ID:48532, VDR_NM:"KEHE FOOD DIST
INC", CPK_ID:"1478952-12", CPK_DSC:"BAHLSEN COOKIES WAFER ROLL MILK
CHOCOLAT", VDR_IT_CD_ID:"6398", UPC_ID:7056921950.0,
CPK_PRI_FLG:"True", CPK_SRC:"PEF", **FCM_RGLT_TYP_CT:"FSV"P"**,
CPK_P_ORIG_DSC:"", RGLN_EXCL_FLG:"False", BRND_TYP:"" }
Exception
Additional information: Cannot convert object of type 'System.String'
to type 'Meijer.MerchProduct.FCM.Models.ViewModels.FCMCasepackVM'
Even I tried serializing the data before deserialize however getting a different exception
Code:
var jsonSerialiser = new JavaScriptSerializer();
selectedCasePack = jsonSerialiser.Serialize(selectedCasePack);
FCMCasepackVM casepack = jsonSerialiser.Deserialize<FCMCasepackVM>(selectedCasePack);
JSON Data after serialize
"{ P_ID:\"1478952\", P_NM:\"BAHLSEN COOKIES WAFER ROLL MILK CHOCOLATE
3.5 OZ\", BYR_ID:191, BYR_NM:\"BYR_NM\", VDR_ID:48532, VDR_NM:\"KEHE FOOD DIST INC\", CPK_ID:\"1478952-12\", CPK_DSC:\"BAHLSEN COOKIES
WAFER ROLL MILK CHOCOLAT\", VDR_IT_CD_ID:\"6398\",
UPC_ID:7056921950.0, CPK_PRI_FLG:\"True\", CPK_SRC:\"PEF\",
FCM_RGLT_TYP_CT:\"FSV\"P\", CPK_P_ORIG_DSC:\"\", RGLN_EXCL_FLG:\"False\", BRND_TYP:\"\" }"
Exception
Additional information: Invalid object passed in, ':' or '}' expected.
(319): { P_ID:"1478952", P_NM:"BAHLSEN COOKIES WAFER ROLL MILK
CHOCOLATE 3.5 OZ", BYR_ID:191, BYR_NM:"BYR_NM", VDR_ID:48532,
VDR_NM:"KEHE FOOD DIST INC", CPK_ID:"1478952-12", CPK_DSC:"BAHLSEN
COOKIES WAFER ROLL MILK CHOCOLAT", VDR_IT_CD_ID:"6398",
UPC_ID:7056921950.0, CPK_PRI_FLG:"True", CPK_SRC:"PEF",
FCM_RGLT_TYP_CT:"FSV"P", CPK_P_ORIG_DSC:"", RGLN_EXCL_FLG:"False",
BRND_TYP:"" }
can anyone please help me?
Thanks in advance,
Karthik
The JSON you are using is invalid and without knowing your container object of FCMCasepackVM and how you got the JSON it is hard to tell what went wrong where. Here is a simple example using the built in System.Web.Script.Serialization technique with the JavaScriptSerializer.
public class POC
{
public int Id { get; set; }
public string Desc { get; set; }
}
static List<POC> GetPOCOs()
{
return new List<POC>
{
new POC { Id = 1, Desc = "John"},
new POC { Id = 2, Desc = "Jane" },
new POC { Id = 3, Desc = "Joey" }
};
}
static void Main(string[] args)
{
var pocos = GetPOCOs();
var serializer = new JavaScriptSerializer();
var sjson = serializer.Serialize(pocos);
var djson = serializer.Deserialize<List<POC>>(sjson);
Console.ReadLine();
}
When I serialize to JSON in text it should look like this:
[{"Id":1,"Desc":"John"},{"Id":2,"Desc":"Jane"},{"Id":3,"Desc":"Joey"}]
Or a single item may be:
{"Id":1,"Desc":"John"}
NOT:
{Id:1,Desc:"John"}
Generally a key pair system is all JSON is but it needs the key surrounded with quotes to be able to know what it is. If you are ever in doubt, use an online JSON validator like http://jsonlint.com/
Where this json data is serialised? quotes should have escaped during serialisation.
This JSON data is invalid, if you have access to app serialising this json data you should change that to escape quotes in the string. (usually all library does that automatically during serialisation)
Update
Hi Karthik, see following code to serialise the objects in JSON format using newtonsoft's library.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var d = new DoTheWork();
d.SerializeSample();
}
}
public class Sample
{
public string Id { get; set; }
public string Description { get; set; }
}
public class DoTheWork
{
public string SerializeSample()
{
List<Sample> sampleList = new List<Sample>();
sampleList.Add(new Sample { Id = "1", Description = "Karthik" });
sampleList.Add(new Sample { Id = "1", Description = "Sujit" });
sampleList.Add(new Sample { Id = "1", Description = "John\"s" });
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(sw, sampleList);
}
System.Diagnostics.Debug.Write(sb.ToString());
return sb.ToString();
}
}

Each-loop in mandrill using handlebars and Mandrill-dotnet -library

I'm using Mandrill to send emails, and are using Handlebars to render content in the email.
If I add variables like this everything works fine:
Backend:
message.AddRecipientVariable("test#gmail.com", "MYVALUE", "some value");
Html-Template:
<p>{{MYVALUE}}</p>
But if I try to use {{#each}} - the each section in the sent email is empty. What am I doing wrong here. Do I pass the objStringArray the wrong way or is there somthing else missing out to render the loop?
Backend:
var objList = new List<MyObj> {new MyObj() {Qty = "125"}, new MyObj() { Qty = "16"}};
var jsonSerialiser = new JavaScriptSerializer();
var objStringArray = jsonSerialiser.Serialize(objList.ToArray());
message.AddRecipientVariable("test#gmail.com", "VALUES", objStringArray);
message.merge_language = "handlebars";
_mandrillApi.SendMessage(message, templateName, new List<TemplateContent>());
Html-Template:
<ul>
{{#each VALUES}}
<li>{{Qty}}</li>
{{/each}}
</ul>
Handlebars in mandrill
Mandrill-dotnet
According to the library I'm using (Mandrill-DotNet) the method: AddRecipientVariable() only takes type string as the content variable. And the madrill-API wants a list when doing the {{#each}} -thing. So by changing the library source code a bit, I can pass in a regular List<dynamic>() to AddRecipientVariable-s content-parameter instead, and it works perfect.
By changing source-code:
public struct merge_var
{
#region Fields
/// <summary>
/// The content.
/// </summary>
public string content;
/// <summary>
/// The name.
/// </summary>
public string name;
#endregion
}
public void AddRecipientVariable(string recipient, string name, string content)
{
if (this.merge_vars == null)
{
this.merge_vars = new List<rcpt_merge_var>();
}
rcpt_merge_var entry = this.merge_vars.Where(e => e.rcpt == recipient).FirstOrDefault();
if (entry == null)
{
entry = new rcpt_merge_var { rcpt = recipient };
this.merge_vars.Add(entry);
}
var mv = new merge_var { name = name, content = content };
entry.vars.Add(mv);
}
To this (string content to dynamic content) :
public struct merge_var
{
#region Fields
/// <summary>
/// The content.
/// </summary>
public dynamic content;
/// <summary>
/// The name.
/// </summary>
public string name;
#endregion
}
public void AddRecipientVariable(string recipient, string name, dynamic content)
{
if (this.merge_vars == null)
{
this.merge_vars = new List<rcpt_merge_var>();
}
rcpt_merge_var entry = this.merge_vars.Where(e => e.rcpt == recipient).FirstOrDefault();
if (entry == null)
{
entry = new rcpt_merge_var { rcpt = recipient };
this.merge_vars.Add(entry);
}
var mv = new merge_var { name = name, content = content };
entry.vars.Add(mv);
}
I am working with Djrill in Python, so I a not familiar with the library you are using.
But you should make sure your JSON is not nested in a wrong way as mentioned in {{#each ... }} on Mandrill is resulting in an empty string

MongoDB geospatial index in C#

I have been trying to get started but run into the same rock time after time trying to create and query MongoDB with C# official driver. The problem is how to create data with geo information. I am just not finding the answer.
Code:
MongoUrl url = new MongoUrl("mongodb://xxx.xx.x.xx/mydb");
MongoServer server = MongoServer.Create(url);
MongoDatabase database = server.GetDatabase("mydb");
<-- this works fine
BsonDocument[] batch = {
new BsonDocument {
{ "name", "Bran" },
{ "loc", "10, 10" }
},
new BsonDocument {
{ "name", "Ayla" },
{ "loc", "0, 0" }
}
};
places.InsertBatch(batch);
<-- that part is wrong somehow
places.EnsureIndex(IndexKeys.GeoSpatial("loca"));
var queryplaces = Query.WithinCircle("loca", 0, 0, 11);
var cursor = places.Find(queryplaces);
foreach (var hit in cursor)
{
foreach (var VARIABLE in hit)
{
Console.WriteLine(VARIABLE.Value);
}
}
<-- I think that part should show both documents, now showing none. A simple find shows them both.
Would be happy for some help.
example below is in C# (it's important to note order in the array which is longitude, latitude- follows the more logical order of x,y as opposed to the more commonly used form where latitude precedes longitude) :
1.) first your class needs to have this:
public double[] Location { get; set; }
public double Latitude
{
get { return _latitude; }
set
{
Location[1] = value;
_latitude = value;
}
}
public double Longitude
{
get { return _longitude; }
set
{
Location[0] = value;
_longitude = value;
}
}
public MyClass()
{
Location = new double[2];
}
2.) then here is some code to get you started with the official C# driver and doing an insert w/ use of geo indexing:
/// <summary>
/// Inserts object and creates GeoIndex on collection (assumes TDocument is a class
/// containing an array double[] Location where [0] is the x value (as longitude)
/// and [1] is the y value (as latitude) - this order is important for spherical queries.
///
/// Collection name is assigned as typeof(TDocument).ToString()
/// </summary>
/// <param name="dbName">Your target database</param>
/// <param name="data">The object you're storing</param>
/// <param name="geoIndexName">The name of the location based array on which to create the geoIndex</param>
/// <param name="indexNames">optional: a dictionary containing any additional fields on which you would like to create an index
/// where the key is the name of the field on which you would like to create your index and the value should be either SortDirection.Ascending
/// or SortDirection.Descending. NOTE: this should not include geo indexes! </param>
/// <returns>void</returns>
public static void MongoGeoInsert<TDocument>(string dbName, TDocument data, string geoIndexName, Dictionary<string, SortDirection> indexNames = null)
{
Connection connection = new Connection(dbName);
MongoCollection collection = connection.GetMongoCollection<TDocument>(typeof(TDocument).Name, connection.Db);
collection.Insert<TDocument>(data);
/* NOTE: Latitude and Longitude MUST be wrapped in separate class or array */
IndexKeysBuilder keys = IndexKeys.GeoSpatial(geoIndexName);
IndexOptionsBuilder options = new IndexOptionsBuilder();
options.SetName("idx_" + typeof(TDocument).Name);
// since the default GeoSpatial range is -180 to 180, we don't need to set anything here, but if
// we wanted to use something other than latitude/longitude, we could do so like this:
// options.SetGeoSpatialRange(-180.0, 180.0);
if (indexNames != null)
{
foreach (var indexName in indexNames)
{
if (indexName.Value == SortDirection.Decending)
{
keys = keys.Descending(indexName.Key);
}
else if (indexName.Value == SortDirection.Ascending)
{
keys = keys.Ascending(indexName.Key);
}
}
}
collection.EnsureIndex(keys, options);
connection.Db.Server.Disconnect();
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Bson;
using MongoDB.Driver;
namespace MyMongo.Helpers
{
public class Connection
{
private const string DbName = "";
private const string Prefix = "mongodb://";
//private const string Server = "(...):27017/";
private const string Server = "localhost:27017/";
private const string PassWord = "";
private const string UserName = "";
private const string Delimeter = "";
//if using MongoHQ
//private const string Delimeter = ":";
//private const string Prefix = "mongodb://";
//private const string DbName = "(...)";
//private const string UserName = "(...)";
//private const string Server = "#flame.mongohq.com:(<port #>)/";
//private const string PassWord = "(...)";
private readonly string _connectionString = string.Empty;
public MongoDatabase Db { get; private set; }
public MongoCollection Collection { get; private set; }
public Connection()
{
_connectionString = Prefix + UserName + Delimeter + PassWord + Server + DbName;
}
public Connection(string dbName)
{
_connectionString = Prefix + UserName + Delimeter + PassWord + Server + DbName;
Db = GetDatabase(dbName);
}
//mongodb://[username:password#]hostname[:port][/[database][?options]]
public MongoDatabase GetDatabase(string dbName)
{
MongoServer server = MongoServer.Create(_connectionString);
MongoDatabase database = server.GetDatabase(dbName);
return database;
}
public MongoCollection<TDocument> GetMongoCollection<TDocument>(string collectionName, MongoDatabase db, SafeMode safeMode = null)
{
if (safeMode == null) { safeMode = new SafeMode(true); }
MongoCollection<TDocument> result = db.GetCollection<TDocument>(collectionName, safeMode);
return result;
}
}
}
After looking and searching I found the answer here: https://github.com/karlseguin/pots-importer/blob/master/PotsImporter/NodeImporter.cs
This to be read with my first piece of code as this fixes it.
MongoCollection<BsonDocument> places =
database.GetCollection<BsonDocument>("places");
BsonDocument[] batch = {
new BsonDocument { { "name", "Bran" }, { "loc", new BsonArray(new[] { 10, 10 }) } },
new BsonDocument { { "name", "Ayla" }, { "loc", new BsonArray(new[] { 0, 0 }) } }
};
places.InsertBatch(batch);
places.EnsureIndex(IndexKeys.GeoSpatial("loc"));
var queryplaces = Query.WithinCircle("loc", 5, 5, 10);
var cursor = places.Find(queryplaces);
foreach (var hit in cursor)
{
Console.WriteLine("in circle");
foreach (var VARIABLE in hit)
{
Console.WriteLine(VARIABLE.Value);
}
}
As a point of clarification: The problem with the code in the question is that location information should not be stored as a string, but rather as an array of 2 elements (x, y).

Categories