Hi I have been trying to figure out how to get stateCode from a Places object by using stream. I am using lombok to parse the json object which looks like this:
{"post code": "90210", "country": "United States", "country abbreviation": "US", "places": [{"place name": "Beverly Hills", "longitude": "-118.4065", "state": "California", "state abbreviation": "CA", "latitude": "34.0901"}]}
I've constructed a class to process the object like so:
#lombok.Value
public class ZipCode {
#JsonAlias("post code")
private final String postalCode;
private final Set<Places> places;
public ZipCode() {
this.postalCode = null;
this.places = null;
}
public ZipCode(String postalCode, Set<Places> places) {
this.postalCode = postalCode;
this.places = places;
}
#lombok.Value
private static class Places {
#JsonAlias("state abbreviation")
private final String stateCode;
}
}
I thought that if I used
ZipCode zip = getZipObject();
String stateCode = zip.getPlaces().stream().findFirst().toString();
I would be able to get the stateCode as a string. In my example the stateCode should've been "CA". Instead I get Optional[ZipCode.Places(stateCode=NY)]. If anyone could help me with this I would appreciate it. I am keeping the ZipCode class in a separate class. I would like to keep it that way. Most of the examples that I've. seen with using stream tend to use the set object itself. I want to avoid having to make my Places object publicly accessible.
I was able to get the stateCode property by modifying the ZipCode class like so
#lombok.Value
public class ZipCode {
#JsonAlias("post code")
private final String postalCode;
private final Set<Places> places;
#lombok.Value
public static class Places {
#JsonAlias("state abbreviation")
private final String stateCode;
}
}
Then I used stream like so
if(zip.getPlaces().stream().findFirst().isPresent())
String state = zip.getPlaces().stream().findFirst().get().getStateCode();
This produce an output of "CA" for the example json. Hope this helps someone.
Related
How can I store an array of doubles to database using Entity Framework Code-First with no impact on the existing code and architecture design?
I've looked at Data Annotation and Fluent API, I've also considered converting the double array to a string of bytes and store that byte to the database in it own column.
I cannot access the public double[] Data { get; set; } property with Fluent API, the error message I then get is:
The type double[] must be a non-nullable value type in order to use
it as parameter 'T'.
The class where Data is stored is successfully stored in the database, and the relationships to this class. I'm only missing the Data column.
You can do a thing like this :
[NotMapped]
public double[] Data
{
get
{
string[] tab = this.InternalData.Split(',');
return new double[] { double.Parse(tab[0]), double.Parse(tab[1]) };
}
set
{
this.InternalData = string.Format("{0},{1}", value[0], value[1]);
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public string InternalData { get; set; }
Thank you all for your inputs, due to your help I was able to track down the best way to solve this. Which is:
public string InternalData { get; set; }
public double[] Data
{
get
{
return Array.ConvertAll(InternalData.Split(';'), Double.Parse);
}
set
{
_data = value;
InternalData = String.Join(";", _data.Select(p => p.ToString()).ToArray());
}
}
Thanks to these stackoverflow posts:
String to Doubles array and
Array of Doubles to a String
I know it is a bit expensive, but you could do this
class Primitive
{
public int PrimitiveId { get; set; }
public double Data { get; set; }
[Required]
public Reference ReferenceClass { get; set; }
}
// This is the class that requires an array of doubles
class Reference
{
// Other EF stuff
// EF-acceptable reference to an 'array' of doubles
public virtual List<Primitive> Data { get; set; }
}
This will now map a single entity (here 'Reference') to a 'list' of your Primitive class. This is basically to allow the SQL database to be happy, and allow you to use your list of data appropriately.
This may not suit your needs, but will be a way to make EF happy.
It would be far easier if you use List<double> rather then double[]. You already have a table that stores your Data values. You probably have foreign key from some table to the table where your double values are stored. Create another model that reflects the table where doubles are stored and add foreign key mappings in the mappings class. That way you will not need to add some complex background logic which retrieves or stores values in a class property.
In my opinion almost all other answers work on the opposite of how it should be.
Entity EF should manage the string and the array must be generated from it. So the array must be whole read and written only when the string is accessed by EF.
A solution involving logic on Data[] is wrong because, as I wrote in a comment, you would run into paradoxical conditions. In all other conditions the variable must remain a pure array.
By putting the "get" and "set" logic in Data[], as I've seen so far, this happens:
1 - Every time an index access is made to the array, the array is automatically recreated from the string. This is a useless work, think of an iteration in a loop...
2 - when you go to set a single element it is not stored because it passes through "get" and not "set".
If you try to declare Data=new []{0,0,0} then set Data[1]=2 , going to re-read Data[1] the result is 0.
My solution is to completely turn the logic around.
public string Data_string
{
get => string.Join(';', Data??Array.Empty());
set => Data= value == null ? Array.Empty<double>() : Array.ConvertAll(value.Split(';',StringSplitOptions.RemoveEmptyEntries), double.Parse);
}
[NotMapped]
public double[] Data {get;set;}
Obviously this only applies to storing and retrieving data on databases, access to Data_string is exclusive to EF.
Once the string is read from the DB it is associated to Data_string which, through set, creates the Data array.
At this point you can work on Data without affecting the string in any way, like a normal array.
When you will ask EF to save in the DB, through the get in the Data_string property, the string will be completely reconstructed based on the Data elements and then stored as a string.
Practically the string is modified only twice, at the moment of reading from the DB and at the moment of saving.
In my opinion this solution is much more efficient than operating continuously on the string.
Nathan White has the best answer (got my vote).
Here is a small improvement over Joffrey Kern's answer to allow lists of any length (untested):
[NotMapped]
public IEnumerable<double> Data
{
get
{
var tab = InternalData.Split(',');
return tab.Select(double.Parse).AsEnumerable();
}
set { InternalData = string.Join(",", value); }
}
[EditorBrowsable(EditorBrowsableState.Never)]
public string InternalData { get; set; }
Don't use double[] use List insted.
Like this.
public class MyModel{
...
public List<MyClass> Data { get; set; }
...
}
public class MyClass{
public int Id { get; set; }
public double Value { get; set; }
}
All that solution that I see there are bad, because:
If you create table, you don't want to store data like this: "99.5,89.65,78.5,15.5" that's not valid! Firstly its a string that means if you can type letter into it and at the moment when your ASP.NET server call double.Parse it will result in FormatException and that you really don't want!
It's slower, because your server must parse the string. Why parse the string instead getting almost ready data from SQL Server to use?
i know this post is Ancient, but in case someone still needs to do something like this, PLEASE DO NOT USE THE ABOVE SOLUTIONS,
as the above solutions are EXTREMELY inefficient (Performance and Disk Space wise).., the best way is to store the array as a Byte array
public byte[] ArrayData;
[NotMapped]
public double[] Array {
get {
var OutputArray = new double[ArrayData.Length / 8];
for (int i = 0;i < ArrayData.Length / 8;i++)
OutputArray[i] = BitConverter.ToDouble(ArrayData, i * 8);
return OutputArray;
}
set {
var OutputData = new byte[value.Length * 8];
for (int i = 0;i < value.Length;i++) {
var BinaryValue = BitConverter.GetBytes(value[i]);
OutputData[(i*8)] = BinaryValue[0];
OutputData[(i*8)+1] = BinaryValue[1];
OutputData[(i*8)+2] = BinaryValue[2];
OutputData[(i*8)+3] = BinaryValue[3];
OutputData[(i*8)+4] = BinaryValue[4];
OutputData[(i*8)+5] = BinaryValue[5];
OutputData[(i*8)+6] = BinaryValue[6];
OutputData[(i*8)+7] = BinaryValue[7];
}
ArrayData = OutputData;
}
}
`
And if you need more performance, you can go for Unsafe code and use pointers .. instead of BitConverter ..
This is way better than saving double values (that can get huge) as string, then spliting the string array !! and then parsing the strings to double !!!
These getter/setters work on the whole array, but if you need to get just one item from the array, you can make a function that gets a single item from the array with a complexity of O(1) :
for Get :
public double Array_GetValue(int Index) {
return BitConverter.ToDouble(ArrayData, Index * 8);
}
for Set :
public void Array_SetValue(int Index, double Value) {
var BinaryValue = BitConverter.GetBytes(Value);
ArrayData[(Index*8)] = BinaryValue[0];
ArrayData[(Index*8)+1] = BinaryValue[1];
ArrayData[(Index*8)+2] = BinaryValue[2];
ArrayData[(Index*8)+3] = BinaryValue[3];
ArrayData[(Index*8)+4] = BinaryValue[4];
ArrayData[(Index*8)+5] = BinaryValue[5];
ArrayData[(Index*8)+6] = BinaryValue[6];
ArrayData[(Index*8)+7] = BinaryValue[7];
}
If your collection can be null or empty, and you want this to be preserved, do this:
[NotMapped]
public double[] Data
{
get => InternalData != null ? Array.ConvertAll(Data.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), double.Parse) : null;
set => InternalData = value != null ? string.Join(";", value) : null;
}
Also, specify [Column(TypeName = "varchar")] on the string property for a more efficient storage data type.
A perfect enhancement to #Jonas's answer will be to add the necessary annotations. So, a cleaner version would be
[EditorBrowsable(EditorBrowsableState.Never)]
[JsonIgnore]
public string InternalData { get; set; }
[NotMapped]
public double[] Data
{
get => Array.ConvertAll(InternalData.Split(';'), double.Parse);
set
{
InternalData = string.Join(";", value.Select(p => p.ToString(CultureInfo.InvariantCulture)).ToArray());
}
}
The [JsonIgnore] Annotation will ignore the InternalData field from JSON serialization and Swagger UI.
[EditorBrowsable(EditorBrowsableState.Never)] will hide the public method from the IDE IntelliSense
I have an object that, when converted to a JSON string using the JsonConvert.SerializeObject method, will look like this:
{"01":{"CompanyName":"Hertz","Cars":"Ford, BMW, Fiat"},
"02":{"CompanyName":"Avis","Cars":"Dodge, Nash, Buick"}}
How can I use the Formatting parameter to make the result look like this:
{"01":{"CompanyName":"Hertz","Cars":["Ford", "BMW", "Fiat"]},
"02":{"CompanyName":"Avis","Cars":["Dodge", "Nash", "Buick"]}}
As #dbc mentioned in the comments, you cannot use the Formatting parameter of JsonConvert.SerializeObject to affect whether a particular value in the JSON is surrounded by square brackets or not. The Formatting parameter only controls whether or not Json.Net will add indenting and line breaks to the JSON output to make it easier to read by a human.
In JSON, square brackets are used to denote an array of values, as opposed to a single value. So, if you want to add square brackets for a particular property, the easiest way to do that is to change how that property is declared in your class such that it correspondingly represents an array (or list).
Based on your original JSON, I'm assuming you have a class which looks like this:
public class Company
{
public string CompanyName { get; set; }
public string Cars { get; set; }
}
...and you are creating your JSON something like this:
var results = new Dictionary<string, Company>();
results.Add("01", new Company
{
CompanyName = "Hertz",
Cars = "Ford, BMW, Fiat"
});
results.Add("02", new Company
{
CompanyName = "Avis",
Cars = "Dodge, Nash, Buick"
});
string json = JsonConvert.SerializeObject(results);
To get square brackets in the JSON, change the type of your Cars property from string to List<string>:
public class Company
{
public string CompanyName { get; set; }
public List<string> Cars { get; set; }
}
Of course, you will also need to make a corresponding change to the code which populates the results:
var results = new Dictionary<string, Company>();
results.Add("01", new Company
{
CompanyName = "Hertz",
Cars = new List<string> { "Ford", "BMW", "Fiat" }
});
results.Add("02", new Company
{
CompanyName = "Avis",
Cars = new List<string> { "Dodge", "Nash", "Buick" }
});
string json = JsonConvert.SerializeObject(results);
Here is a short demo: https://dotnetfiddle.net/lgg9jk
I've declared an API call in an interface and was wondering if it is possible to put constraints on some of the parameters. The API I'm accessing has these constraints as well and would like to enforce them in my program.
#GET("/recipes/search")
Call<RecipeResponse> getRecipes(
#Query("cuisine") String cuisine,
#Query("diet") String diet,
#Query("excludeIngredients") String excludeIngredients,
#Query("intolerances") String intolerances,
#Query("number") Integer number,
#Query("offset") Integer offset,
#Query("query") String query,
#Query("type") String type
);
How can I do this?
I know that it is possible to do this with POST request, and passing along an object via the RequestBody through the #Body annotation. Can I do this with a GET request too, where information is passed via the query string?
Thanks!
I think I ended up finding a solution. I've made a class SearchRecipeRequest in which I declare all possible parameters as class variables. In the setters I do the data validation such as checking for null on parameters that are required, or min/max value constraints on integers as specified by the endpoint. I then made a SearchRecipeRequestBuilder class to build such an object like so to make it easier to deal with all those possible parameters:
public class SearchRecipeRequestBuilder {
private String _cuisine = null,
_diet = null,
_excludeIngredients = null,
_intolerances = null,
_query = null,
_type = null;
private Integer _number = null,
_offset = null;
public SearchRecipeRequestBuilder() {}
public SearchRecipeRequest buildRequest() {
return new SearchRecipeRequest(_cuisine, _diet, _excludeIngredients, _intolerances, _number, _offset, _query, _type);
}
public SearchRecipeRequestBuilder cuisine(String cuisine) {
_cuisine = cuisine;
return this;
}
public SearchRecipeRequestBuilder diet(String diet) {
_diet = diet;
return this;
}
public SearchRecipeRequestBuilder excludeIngredients(String excludeIngredients) {
_excludeIngredients = excludeIngredients;
return this;
}
public SearchRecipeRequestBuilder intolerances(String intolerances) {
_intolerances = intolerances;
return this;
}
public SearchRecipeRequestBuilder query(String query) {
_query = query;
return this;
}
public SearchRecipeRequestBuilder type(String type) {
_type = type;
return this;
}
public SearchRecipeRequestBuilder number(Integer number) {
_number = number;
return this;
}
public SearchRecipeRequestBuilder offset(Integer offset) {
_offset = offset;
return this;
}
}
Which allows me to build the request like so:
SearchRecipeRequest request = new SearchRecipeRequestBuilder()
.query("burger")
.buildRequest();
I then pass along that object to a different function that knows how to use the request object to pass it along to the API.
That's how I'm doing it right now, if someone has a better way I'd love to hear it. :)
I got the idea to use the Builder pattern from a different StackOverflow question: Managing constructors with many parameters in Java.
When I try to index a doc of my defined type, having a list which is supposed to be mapped as a nested-object ("type":"nested"), it's getting mapped as a regular object type.
Take a look at the code:
I've got a simple class like this one:
[ElasticType()]
public class MyJob
{
[ValueFieldAttribute]
public int jobCode { get; set; }
[ValueFieldAttribute(Type = FieldType.nested)]
public IList<JobProfessionalFieldInfo> JobProfessionalFields { get; set; }
}
The code for the JobProfessionalFieldInfo class is:
[ElasticType()]
public class JobProfessionalFieldInfo
{
[ValueFieldAttribute]
public int JobId { get; set; }
[ValueFieldAttribute]
public int CategoryId { get; set; }
}
The code for the ValueFieldAttribute class is:
public class ValueFieldAttribute : ElasticPropertyAttribute
{
public ValueFieldAttribute()
: base()
{
this.Store = false;
this.Index = FieldIndexOption.not_analyzed;
}
}
My program:
static void Main(string[] args)
{
ConnectionSettings node = new ConnectionSettings(new Uri("http://localhost:9200"));
node.SetDefaultIndex("jobs");
ElasticClient client = new ElasticClient(node);
List<JobProfessionalFieldInfo> list = new List<JobProfessionalFieldInfo>();
list.Add(new JobProfessionalFieldInfo { CategoryId = 1, JobId = 1 });
list.Add(new JobProfessionalFieldInfo { CategoryId = 2, JobId = 2 });
var res = client.Index<MyJob>(new MyJob
{
jobCode = 1,
JobProfessionalFields = list
},"jobs", "MyJob",1);
}
Now, when I run it, it indexes the object successfully... BUT(!!) when I get the mapping of the index with GET jobs/MyJob/_mapping, I see that jobProfessionalFields has no "type":"nested" in its mapping.
That results in a query like the following one, returning the indexed doc while it's not supposed to get it back (that's what nested-type is for right?..):
GET jobs/_search
{
"query":
{
"bool":
{
"must":
[
{"match": {"jobId":1}},
{"match": {"categoryId":2}}
]
}
}
}
It's not the end:
I'd a look at here,
there the guy that answered tells that when we use annotations we need to manually call the createIndex and Map methods, but the problem is that I don't have any generic Map method...!
Take a look at here: (just to make you get into the link - here's its start..)
namespace Nest
{
public partial class ElasticClient...
And I don't know how to use the non-generic Map method to put the mapping of my MyJob class.
How can I cause this stuff to map the jobProfessionalFields as nested-type dudes?
Thanks for any help of you guys!
OK, got it LOL!
The MapFromAttributes<> is the right generic method for putting the mapping (at least in the current Nest version I'm using - 0.12.0).
But it demands a manual call for the index creationg, o.w it gives an IndexMissing exception (like the guy in the above mentioned link said).
client.CreateIndex("jobs", new IndexSettings { });
var res = client.MapFromAttributes<MyJob>("jobs","MyJob");
But that's really interesting why isn't it enough to just define the
[ElasticProperty(Type = FieldType.nested)],
in order to get the nested mapping though..
I would be glad to get an answer for that one.
I am using JSON.Net to serialize my objects. For eg, if this is my object
Class MainData
{
[JsonProperty("keyValues")]
string val;
}
the data for 'val' is a key value pair string like this key1:value1.
I have a scenario where I should not get the above 'keyValues' name in my final serialized string and instead get a serialized string which looks like this
{
"key1":"value1"
}
Currently with my serializer I am getting this, which is not what I need
{
"keyValues":"key:value1"
}
Can somebody guide me to any documentation/solution to dynamically assign the name of the field instead of using the default variable name/JSONProperty Name defined inside the object?
Thanks a lot in advance.
I've been struggling with this all day, what I've done is used a dictionary object and serialised this
however I had an error message that was "cannot serialise dictionary", should have read the whole message, "cannot serialise dictionary when the key is not a string or object"
this now works for me and gives me a key/value pair
i have the following objects
public class Meal {
public int mealId;
public int value;
public Meal(int MealId, int Value) {
mealId = MealId;
value = Value;
} }
public class Crew
{
public Meal[] AllocatedMeals {
get {
return new Meal[]{
new Meal(1085, 2),
new Meal(1086, 1) }; } }
public int AllocatedMealTotal {
get {
return this.AllocatedMeals.Sum(x => x.value); } }
}
then the following code
Dictionary<string,string> MealsAllocated = crew.AllocatedMeals.ToDictionary(x => x.mealId.ToString(), x => x.value.ToString());
return new JavaScriptSerializer().Serialize(
new {
Allocated = new {
Total = crew.AllocatedMealTotal,
Values = MealsAllocated } )
to get
"Allocated":{"Total":3,"Values":{"1085":"2","1086":"1"}}