I'm a user for libarry Json.NET Schema, is there a function for generate json sample by given the json schema?
I finally tried another way to get the result, refer the function:
/// <summary>
/// Generate a random Json sample based on json schema
/// </summary>
/// <param name="schema"></param>
/// <returns>a random Json sample</returns>
public static JToken GenerateJsonSample(this JSchema schema)
{
JToken output;
switch (schema.Type)
{
case JSchemaType.Object:
var jObject = new JObject();
if (schema.Properties != null)
{
foreach (var prop in schema.Properties)
{
jObject.Add(LowerCaseFirstChar(prop.Key), GenerateJsonSample(prop.Value));
}
}
output = jObject;
break;
case JSchemaType.Object | JSchemaType.Null:
var jObject2 = new JObject();
if (schema.Properties != null)
{
foreach (var prop in schema.Properties)
{
jObject2.Add(LowerCaseFirstChar(prop.Key), GenerateJsonSample(prop.Value));
}
}
output = jObject2;
break;
case JSchemaType.Array:
var jArray = new JArray();
foreach (var item in schema.Items)
{
jArray.Add(GenerateJsonSample(item));
}
output = jArray;
break;
case JSchemaType.Array | JSchemaType.Null:
var jArray2 = new JArray();
foreach (var item in schema.Items)
{
jArray2.Add(GenerateJsonSample(item));
}
output = jArray2;
break;
case JSchemaType.String:
output = new JValue("string_sample");
break;
case JSchemaType.String | JSchemaType.Null:
output = new JValue("nullable_string_sample");
break;
case JSchemaType.Number:
output = new JValue(1.0);
break;
case JSchemaType.Integer:
output = new JValue(1);
break;
case JSchemaType.Boolean:
output = new JValue(false);
break;
case JSchemaType.Null:
output = JValue.CreateNull();
break;
default:
output = null;
break;
}
return output;
}
private static string LowerCaseFirstChar(string name)
{
return name.Substring(0, 1).ToLower() + name.Substring(1);
}
then, your calling code would be:
var sampleJsonContent = yourJSchema.GenerateJsonSample().ToString();
Related
I would like to evaluate a CSV data series with Xunit.
For this I need to read in a string consisting of int, bool, double and others.
With the following code, the transfer basically works for one row.
But since I want to test for predecessor values, I need a whole CSV file for evaluation.
My [Theory] works with InlineData without errors.
But when I read in a CSV file, the CSVDataHandler gives a System.ArgumentOutOfRangeException!
I can't find a solution for the error and ask for support.
Thanks a lot!
[Theory, CSVDataHandler(false, "C:\\MyTestData.txt", Skip = "")]
public void TestData(int[] newLine, int[] GetInt, bool[] GetBool)
{
for (int i = 0; i < newLine.Length; i++)
{
output.WriteLine("newLine {0}", newLine[i]);
output.WriteLine("GetInt {0}", GetInt[i]);
output.WriteLine("GetBool {0}", GetBool[i]);
}
}
[DataDiscoverer("Xunit.Sdk.DataDiscoverer", "xunit.core")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class DataArribute : Attribute
{
public abstract IEnumerable<object> GetData(MethodInfo methodInfo);
public virtual string? Skip { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : DataAttribute
{
public CSVDataHandler(bool hasHeaders, string pathCSV)
{
this.hasHeaders = hasHeaders;
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
var methodParameters = methodInfo.GetParameters();
var paramterTypes = methodParameters.Select(p => p.ParameterType).ToArray();
using (var streamReader = new StreamReader(pathCSV))
{
if (hasHeaders) { streamReader.ReadLine(); }
string csvLine = string.Empty;
// ReadLine ++
//while ((csvLine = streamReader.ReadLine()) != null)
//{
// var csvRow = csvLine.Split(',');
// yield return ConvertCsv((object[])csvRow, paramterTypes);
//}
// ReadToEnd ??
while ((csvLine = streamReader.ReadToEnd()) != null)
{
if (Environment.NewLine != null)
{
var csvRow = csvLine.Split(',');
yield return ConvertCsv((object[])csvRow, paramterTypes); // System.ArgumentOutOfRangeException
}
}
}
}
private static object[] ConvertCsv(IReadOnlyList<object> cswRow, IReadOnlyList<Type> parameterTypes)
{
var convertedObject = new object[parameterTypes.Count];
for (int i = 0; i < parameterTypes.Count; i++)
{
convertedObject[i] = (parameterTypes[i] == typeof(int)) ? Convert.ToInt32(cswRow[i]) : cswRow[i]; // System.ArgumentOutOfRangeException
convertedObject[i] = (parameterTypes[i] == typeof(double)) ? Convert.ToDouble(cswRow[i]) : cswRow[i];
convertedObject[i] = (parameterTypes[i] == typeof(bool)) ? Convert.ToBoolean(cswRow[i]) : cswRow[i];
}
return convertedObject;
}
}
MyTestData.txt
1,2,true,
2,3,false,
3,10,true,
The first call to streamReader.ReadToEnd() will return the entire contents of the file in a string, not just one line. When you call csvLine.Split(',') you will get an array of 12 elements.
The second call to streamReader.ReadToEnd() will not return null as your while statement appears to expect, but an empty string. See the docu at
https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readtoend?view=net-7.0
If the current position is at the end of the stream, returns an empty
string ("").
With the empty string, the call to call csvLine.Split(',') will return an array of length 0, which causes your exception when its first element (index 0) is accessed.
All of this could have been easily discovered by simply starting the test in a debugger.
It looks like you have some other issues here as well.
I don't understand what your if (Environment.NewLine != null) is intended to do, the NewLine property will never be null but should have one of the values "\r\n" or "\n" so the if will always be taken.
The parameters of your test method are arrays int[] and bool[], but you are checking against the types int, double and bool in your ConvertCsv method, so the alternative cswRow[i] will always be returned. You'll wind up passing strings to your method expecting int[] and bool[] and will at latest get an error there.
This method reads a data series from several rows and columns and returns it as an array for testing purposes.
The conversion of the columns can be adjusted according to existing pattern.
Thanks to Christopher!
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : Xunit.Sdk.DataAttribute
{
public CSVDataHandler(string pathCSV)
{
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
List<int> newLine = new();
List<int> GetInt = new();
List<bool> GetBool = new();
var reader = new StreamReader(pathCSV);
string readData = string.Empty;
while ((readData = reader.ReadLine()) != null)
{
string[] split = readData.Split(new char[] { ',' });
newLine.Add(int.Parse(split[0]));
GetInt.Add(int.Parse(split[1]));
GetBool.Add(bool.Parse(split[2]));
// Add more objects ...
}
yield return new object[] { newLine.ToArray(), GetInt.ToArray(), GetBool.ToArray() };
}
}
I have this Action method which act as an API end point inside our ASP.NET MVC-5, where it search for a username and return the username Phone number and Department from Active Directory (we are serializing the object using Newtonsoft.net):-
public ActionResult UsersInfo2()
{
DomainContext result = new DomainContext();
try
{
// create LDAP connection object
DirectoryEntry myLdapConnection = createDirectoryEntry();
string ADServerName = System.Web.Configuration.WebConfigurationManager.AppSettings["ADServerName"];
string ADusername = System.Web.Configuration.WebConfigurationManager.AppSettings["ADUserName"];
string ADpassword = System.Web.Configuration.WebConfigurationManager.AppSettings["ADPassword"];
using (var context = new DirectoryEntry("LDAP://mydomain.com:389/DC=mydomain,DC=com", ADusername, ADpassword))
using (var search = new DirectorySearcher(context))
{
// create search object which operates on LDAP connection object
// and set search object to only find the user specified
// DirectorySearcher search = new DirectorySearcher(myLdapConnection);
// search.PropertiesToLoad.Add("telephoneNumber");
search.Filter = "(&(objectClass=user)(sAMAccountName=test.test))";
SearchResult r = search.FindOne();
ResultPropertyCollection fields = r.Properties;
foreach (String ldapField in fields.PropertyNames)
{
// cycle through objects in each field e.g. group membership
// (for many fields there will only be one object such as name)
string temp;
// foreach (Object myCollection in fields[ldapField])
// {
// temp = String.Format("{0,-20} : {1}",
// ldapField, myCollection.ToString());
if (ldapField.ToLower() == "telephonenumber")
{
foreach (Object myCollection in fields[ldapField])
{
result.Telephone = myCollection.ToString();
}
}
else if (ldapField.ToLower() == "department")
{
foreach (Object myCollection in fields[ldapField])
{
result.Department = myCollection.ToString();
}
}
// }
}
string output = JsonConvert.SerializeObject(result);
return Json(output,JsonRequestBehavior.AllowGet);
}
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return View(result);
}
now the return JSON will be as follow:-
"\"DisplayName\":null,\"Telephone\":\"123123\",\"Department\":\"IT\",\"Name\":null,\"SamAccountName\":null,\"DistinguishedName\":null,\"UserPrincipalName\":null}"
but in our case we need to return a status code beside the return json data. for example inccase there is an exception we need to return an error code,also if we are able to get the user's info we need to pass succes code 200, and so on.. so how we can achieve this?
you can try something like this
var statusCode=200;
string output = JsonConvert.SerializeObject( new { result = result, StatusCode = statusCode);
but nobody usually do this. When users call API they can check status code that HTTP Client returns, using code like this
var response = await client.GetAsync(api);
//or
var response = await client.PutAsJsonAsync(api, data);
var statusCode = response.StatusCode.ToString();
//or usually
if (response.IsSuccessStatusCode) {...}
else {...}
I have this C# method is asp.net webapi :
public IHttpActionResult Definitions()
{
var words = db.Words
.Where(w => w.Name == "abandon")
.AsNoTracking()
.ToList();
foreach (var word in words)
{
HttpResponse<string> response = Unirest.get("https://wordsapiv1.p.mashape.com/words/" + word.Name)
.header("X-Mashape-Key", "xxx")
.header("Accept", "application/json")
.asJson<string>();
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(response.Body);
var results = rootObject.results;
foreach (var result in results)
{
if (!(from d in db.WordDefinitions where d.Definition == result.definition select d).Any())
{
var pos = 0;
switch (result.partOfSpeech)
{
case "noun":
pos = 1;
break;
case "verb":
pos = 2;
break;
case "adjective":
pos = 3;
break;
case "Adverb":
pos = 4;
break;
default:
pos = 5;
break;
}
var definition = new WordDefinition()
{
WordId = word.WordId,
Definition = result.definition,
PosId = pos
};
db.WordDefinitions.Add(definition);
}
db.SaveChanges();
}
}
return Ok();
}
The code runs from start to finish. When I put a breakpoint on db.SaveChanges() I see it reaching that point multiple times and I see that definition is populated.
But when I check the database there's nothing added.
Is there a way that I can add some checks that might point me to what is going wrong? I suspected there was an exception but then I think not as the code keeps running right to the end of the method.
Try doing that db.SaveChanges after the complete lists gets added to WordDefinitions.. I mean after the scope of outer foreach.. Its better to have that line of code outside the scope because each time it will hit the db and save your data which will relatively take some more time when compared to doing like this...
Code:
public IHttpActionResult Definitions()
{
var words = db.Words
.Where(w => w.Name == "abandon")
.AsNoTracking()
.ToList();
foreach (var word in words)
{
HttpResponse<string> response = Unirest.get("https://wordsapiv1.p.mashape.com/words/" + word.Name)
.header("X-Mashape-Key", "xxx")
.header("Accept", "application/json")
.asJson<string>();
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(response.Body);
var results = rootObject.results;
foreach (var result in results)
{
if (!(from d in db.WordDefinitions where d.Definition == result.definition select d).Any())
{
var pos = 0;
switch (result.partOfSpeech)
{
case "noun":
pos = 1;
break;
case "verb":
pos = 2;
break;
case "adjective":
pos = 3;
break;
case "Adverb":
pos = 4;
break;
default:
pos = 5;
break;
}
var definition = new WordDefinition()
{
WordId = word.WordId,
Definition = result.definition,
PosId = pos
};
db.WordDefinitions.Add(definition);
}
}
}
db.SaveChanges();
return Ok();
}
I have following error in this code: Cannot infer type arguments for ReadOnlyListWrapper<>
How should my return type look like? I need to save arraylist for each node in all columns. But I can not return it.
for (Entry<String, String> ent : dc.getSortedOrgAll().entrySet()) {
TreeTableColumn<String, ArrayList<String>> col = new TreeTableColumn<>(
ent.getValue());
col.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<String, ArrayList<String>>, ObservableValue<ArrayList<String>>>() {
#Override
public ObservableValue<ArrayList<String>> call(
CellDataFeatures<String, ArrayList<String>> param) {
TreeMap<String, List<String>> temp = (TreeMap<String, List<String>>) dc
.getFuncTypeOrg().clone();
ArrayList<String> result = new ArrayList<>();
for (int i = 0; i < temp.size(); i++) {
List<String> list = temp.firstEntry().getValue();
String key = temp.firstEntry().getKey();
// root.getChildren();
if (list.get(1).equals("Papier")) {
System.out.println(list.get(1));
}
if (list.get(1).equals(param.getValue().getValue())
&& list.get(5).equals(col.getText())) {
result.add(list.get(2));
if(list.size()==9)
result.add(list.get(list.size()-1));
else result.add("White");
} else {
temp.remove(key);
// result = null;
}
}
return new ReadOnlyListWrapper<>(result);
}
});
ReadOnlyListWrapper<T> implements ObservableValue<ObservableList<T>>, which isn't what you need, as you declared the callback to return an ObservableValue<ArrayList<T>> (T is just String here).
So I think you just need
return new ReadOnlyObjectWrapper<ArrayList<String>>(result);
and you can probably omit the generic type:
return new ReadOnlyObjectWrapper<>(result);
Just a comment: I think you could make your life much easier by defining some actual data model classes, instead of trying to force your data into various collections implementations.
I am having a info class with following field like id,name,address and i have created list of that info like List.
I want to have all the values of list into comma seperated strings using linq. Is there any way for this.
simple way... may not be the fastest so it depends on how many records you are processing
var myObjects = new[] {
new {
id=1,
name="Matt",
address="1234 no chance ln\r\nnowhere, OH 12345"
},
new {
id=1,
name="Jim",
address="4321 no chance ln\r\nnowhere, OH 12345"
}
};
var myList = (from o in myObjects
select string.Format("{0},\"{1}\",\"{2}\"",
o.id,
o.name,
(o.address ?? string.Empty).Replace("\r\n", ";")
)).ToList();
Have a look at this example by Mike Hadlow. It needs some improvement (escaping commas, new line support etc) but gives you the basic idea.
Taken from the LinQExtensions.cs found at Batch Updates and Deletes with LINQ to SQL
/// <summary>
/// Creates a *.csv file from an IQueryable query, dumping out the 'simple' properties/fields.
/// </summary>
/// <param name="query">Represents a SELECT query to execute.</param>
/// <param name="fileName">The name of the file to create.</param>
/// <remarks>
/// <para>If the file specified by <paramref name="fileName"/> exists, it will be deleted.</para>
/// <para>If the <paramref name="query"/> contains any properties that are entity sets (i.e. rows from a FK relationship) the values will not be dumped to the file.</para>
/// <para>This method is useful for debugging purposes or when used in other utilities such as LINQPad.</para>
/// </remarks>
public static void DumpCSV(this IQueryable query, string fileName)
{
query.DumpCSV(fileName, true);
}
/// <summary>
/// Creates a *.csv file from an IQueryable query, dumping out the 'simple' properties/fields.
/// </summary>
/// <param name="query">Represents a SELECT query to execute.</param>
/// <param name="fileName">The name of the file to create.</param>
/// <param name="deleteFile">Whether or not to delete the file specified by <paramref name="fileName"/> if it exists.</param>
/// <remarks>
/// <para>If the <paramref name="query"/> contains any properties that are entity sets (i.e. rows from a FK relationship) the values will not be dumped to the file.</para>
/// <para>This method is useful for debugging purposes or when used in other utilities such as LINQPad.</para>
/// </remarks>
public static void DumpCSV(this IQueryable query, string fileName, bool deleteFile)
{
if (File.Exists(fileName) && deleteFile)
{
File.Delete(fileName);
}
using (var output = new FileStream(fileName, FileMode.CreateNew))
{
using (var writer = new StreamWriter(output))
{
var firstRow = true;
PropertyInfo[] properties = null;
FieldInfo[] fields = null;
Type type = null;
bool typeIsAnonymous = false;
foreach (var r in query)
{
if (type == null)
{
type = r.GetType();
typeIsAnonymous = type.IsAnonymous();
properties = type.GetProperties();
fields = type.GetFields();
}
var firstCol = true;
if (typeIsAnonymous)
{
if (firstRow)
{
foreach (var p in properties)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
writer.Write(p.Name);
}
writer.WriteLine();
}
firstRow = false;
firstCol = true;
foreach (var p in properties)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
DumpValue(p.GetValue(r, null), writer);
}
}
else
{
if (firstRow)
{
foreach (var p in fields)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
writer.Write(p.Name);
}
writer.WriteLine();
}
firstRow = false;
firstCol = true;
foreach (var p in fields)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
DumpValue(p.GetValue(r), writer);
}
}
writer.WriteLine();
}
}
}
}
private static void DumpValue(object v, StreamWriter writer)
{
if (v != null)
{
switch (Type.GetTypeCode(v.GetType()))
{
// csv encode the value
case TypeCode.String:
string value = (string)v;
if (value.Contains(",") || value.Contains('"') || value.Contains("\n"))
{
value = value.Replace("\"", "\"\"");
if (value.Length > 31735)
{
value = value.Substring(0, 31732) + "...";
}
writer.Write("\"" + value + "\"");
}
else
{
writer.Write(value);
}
break;
default: writer.Write(v); break;
}
}
}
private static bool IsAnonymous(this Type type)
{
if (type == null)
throw new ArgumentNullException("type");
// HACK: The only way to detect anonymous types right now.
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}