How to write a nested object using protobuf syntax? - protocol-buffers

I would like to convert this nested object to it's equivalent in protobuf syntax:
{
where: {
id: string | { equals: string }
}
}
So the id field could either be a string or an object with a single key called equals.
I tried a little bit and did some research, but I just couldn't figure out how.
message UserRequest {
string id = 1;
}
message UserQuery {
UserRequest where = 1;
}
And of course, I want to avoid using google.protobuf.Any.

message Foo {
oneof where {
string id = 1;
Bar bar_message = 2;
}
}
message Bar {
string equals = 1;
}

Related

.Net dictionary type in protobuff

Can you help me identify this type in protobuff. Error is missing ">"
class SomeRequest
{
Dictionary<long,List<string>> values;
}
message SomeRequest
{
map<int64,repeated string> values = 1;
}
Basically, you can't do that. The closest you can get is a map to something that has a repeated element, so:
message SomeRequest
{
map<int64,Thing> values = 1;
}
message Thing {
repeated string items = 1;
}
Or in c# terms:
class SomeRequest
{
Dictionary<long,Thing> values;
}
class Thing
{
List<string> items;
}

Dart - Best sort Algorithm for pushing a list of objects to a list of First Class Lists

I have a list of objects that are retrieved from a DB. The object looks like this:
class MonthlyFinancePlan {
final int id;
final DateTime date;
final double incomeAfterTax;
final double totalToPayOut;
final double totalRemainingForMonth;
final Map<String, dynamic> items;
MonthlyFinancePlan({ this.id, this.date, this.incomeAfterTax, this.totalToPayOut, this.totalRemainingForMonth, this.items });
MonthlyFinancePlan.fromEntity(MonthlyFinancePlanEntity monthlyFinancePlanEntity):
this.id = monthlyFinancePlanEntity.id,
this.date = DateTime.parse(monthlyFinancePlanEntity.date),
this.incomeAfterTax = monthlyFinancePlanEntity.incomeAfterTax.toDouble(),
this.totalToPayOut = monthlyFinancePlanEntity.totalToPayOut.toDouble(),
this.totalRemainingForMonth = monthlyFinancePlanEntity.moneyRemainingForMonth.toDouble(),
this.items = monthlyFinancePlanEntity.items != null ? json.decode(monthlyFinancePlanEntity.items) : Map();
}
I need to sort these by date.year and then pass them into a first class List, I'd like to create a List of these First class lists so that all the MonthlyFinancePlan objects that are from the year 2020 are sorted and contained within the first class list, same for 2021, etc.
The first class list looks like this:
class YearlyFinancePlan {
List<MonthlyFinancePlan> _monthlyFinancePlanList;
int _year;
double _totalIncomeForYear;
double _totalOutGoingsForYear;
List<MonthlyFinancePlan> get items {
return this._monthlyFinancePlanList;
}
int get year {
return this._year;
}
double get totalIncomeForYear {
return this._totalIncomeForYear;
}
double get totalOutgoingsForYear {
return this._totalOutGoingsForYear;
}
YearlyFinancePlan(this._monthlyFinancePlanList) {
this._year = this._monthlyFinancePlanList.first.date.year;
this._totalIncomeForYear = this._setTotalIncomeFromList(this._monthlyFinancePlanList);
this._totalOutGoingsForYear = this._setTotalOutGoingsForYear(this._monthlyFinancePlanList);
}
double _setTotalIncomeFromList(List<MonthlyFinancePlan> monthlyFinancePlanList) {
double totalIncome;
monthlyFinancePlanList.forEach((plan) => totalIncome += plan.incomeAfterTax);
return totalIncome;
}
double _setTotalOutGoingsForYear(List<MonthlyFinancePlan> monthlyFinancePlanList) {
double totalOutgoings;
monthlyFinancePlanList.forEach((plan) => totalOutgoings += plan.totalToPayOut);
return totalOutgoings;
}
}
My question is, what sort algorithm would be best suited for what I need? I don't have any code to show as I don't know what sort algorithm to use. I'm not looking for anyone to write my code, but more to guide me through it.
Any help would be greatly appreciated
I've created a Mapper that checks if the MonthlyPlanner.date.year exists as a key in a standard Dart Map and adds it if it doesn't exist. Once the check is complete, it also calls the addMonthlyPlan method to add the entry to the MonthlyPlan to the correct YearlyPlan like so:
class FinancePlanMapper {
static Map<int, YearlyFinancePlan> toMap(List<MonthlyFinancePlan> planList) {
Map<int, YearlyFinancePlan> planMap = Map();
planList.forEach((monthlyPlan) {
planMap.putIfAbsent(monthlyPlan.date.year, () => YearlyFinancePlan(List()));
planMap[monthlyPlan.date.year].addMonthlyPlan(monthlyPlan);
});
return planMap;
}
}
I'm not too sure whether it's the most efficient way of sorting but I plan to refactor it as much as possible. I've also updated the YearlyFinancePlan object so that it doesn't initialise any fields on construction, which would cause the object to throw an error when being initialised with an empty list:
class YearlyFinancePlan {
List<MonthlyFinancePlan> _monthlyFinancePlanList;
List<MonthlyFinancePlan> get items {
return this._monthlyFinancePlanList;
}
int get year {
return this.items.first.date.year;
}
double get totalIncomeForYear {
return this._setTotalIncomeFromList(this._monthlyFinancePlanList);
}
double get totalOutgoingsForYear {
return this._setTotalOutGoingsForYear(this._monthlyFinancePlanList);
}
YearlyFinancePlan(this._monthlyFinancePlanList);
void addMonthlyPlan(MonthlyFinancePlan plan) {
this._monthlyFinancePlanList.add(plan);
}
double _setTotalIncomeFromList(List<MonthlyFinancePlan> monthlyFinancePlanList) {
double totalIncome = 0;
monthlyFinancePlanList.forEach((plan) => totalIncome += plan.incomeAfterTax);
return totalIncome;
}
double _setTotalOutGoingsForYear(List<MonthlyFinancePlan> monthlyFinancePlanList) {
double totalOutgoings = 0;
monthlyFinancePlanList.forEach((plan) => totalOutgoings += plan.totalToPayOut);
return totalOutgoings;
}
}

Dealing with one field that is sometimes boolean and sometimes int

I'm trying to work with the reddit JSON API. There are post data objects that contain a field called edited which may contain a boolean false if the post hasn't been edited, or a timestamp int if the post was edited.
Sometimes a boolean:
{
"edited": false,
"title": "Title 1"
}
Sometimes an int:
{
"edited": 1234567890,
"title": "Title 2"
}
When trying to parse the JSON where the POJO has the field set to int, I get an error: JsonDataException: Expected an int but was BOOLEAN...
How can I deal with this using Moshi?
I also ran into a similar problem where I had fields that were sometimes booleans, and sometimes ints. I wanted them to always be ints. Here's how I solved it with Moshi and kotlin:
Make a new annotation that you will use on fields to should convert from boolean to int
#JsonQualifier
#Retention(AnnotationRetention.RUNTIME)
#Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION)
annotation class ForceToInt
internal class ForceToIntJsonAdapter {
#ToJson
fun toJson(#ForceToInt i: Int): Int {
return i
}
#FromJson
#ForceToInt
fun fromJson(reader: JsonReader): Int {
return when (reader.peek()) {
JsonReader.Token.NUMBER -> reader.nextInt()
JsonReader.Token.BOOLEAN -> if (reader.nextBoolean()) 1 else 0
else -> {
reader.skipValue() // or throw
0
}
}
}
}
Use this annotation on the fields that you want to force to int:
#JsonClass(generateAdapter = true)
data class Discovery(
#Json(name = "id") val id: String = -1,
#ForceToInt #Json(name = "thanked") val thanked: Int = 0
)
The easy way might be to make your Java edited field an Object type.
The better way for performance, error catching, and appliaction usage is to use a custom JsonAdapter.
Example (edit as needed):
public final class Foo {
public final boolean edited;
public final int editedNumber;
public final String title;
public static final Object JSON_ADAPTER = new Object() {
final JsonReader.Options options = JsonReader.Options.of("edited", "title");
#FromJson Foo fromJson(JsonReader reader) throws IOException {
reader.beginObject();
boolean edited = true;
int editedNumber = -1;
String title = "";
while (reader.hasNext()) {
switch (reader.selectName(options)) {
case 0:
if (reader.peek() == JsonReader.Token.BOOLEAN) {
edited = reader.nextBoolean();
} else {
editedNumber = reader.nextInt();
}
break;
case 1:
title = reader.nextString();
break;
case -1:
reader.nextName();
reader.skipValue();
default:
throw new AssertionError();
}
}
reader.endObject();
return new Foo(edited, editedNumber, title);
}
#ToJson void toJson(JsonWriter writer, Foo value) throws IOException {
writer.beginObject();
writer.name("edited");
if (value.edited) {
writer.value(value.editedNumber);
} else {
writer.value(false);
}
writer.name("title");
writer.value(value.title);
writer.endObject();
}
};
Foo(boolean edited, int editedNumber, String title) {
this.edited = edited;
this.editedNumber = editedNumber;
this.title = title;
}
}
Don't forget to register the adapter on your Moshi instance.
Moshi moshi = new Moshi.Builder().add(Foo.JSON_ADAPTER).build();
JsonAdapter<Foo> fooAdapter = moshi.adapter(Foo.class);

Can I override/delegate assignment operator?

I began learn Groovy, and faced the challenge.
I have this code, that stores meta-data to object:
class Meta {
final MetaItem name
final MetaItem description
// ...
// And more fields with type MetaItem
// ...
Meta() {
name = new MetaItem("name")
description = new MetaItem("description")
}
void setName(String name) {
this.name.value = name
}
String getName() {
return this.name.value
}
void setDescription(String description) {
this.description.value = description
}
String getDescription() {
return this.description.value
}
// ...
// And more methods. Two for each field
// ...
}
class MetaItem {
private final def id
def value
MetaItem(String id) {
this.id = id
}
}
// Validating
def meta = new Meta()
assert meta.name == null
assert meta.description == null
meta.with {
name = "Name"
description = "Desc"
}
assert meta.name == "Name"
assert meta.description == "Desc"
print "Success!"
As you can see from the code, it increases quicly in volumes when new fields are added, because for each field you need to add two methods. Can this somehow be optimized? Redirect the assignment operation from object to his member. I've looked on Delegate, but this is not what I need.
P.S. I can't use access by .value because this class is used in Gradle extension and I need to configure it like this:
myExtension {
meta {
name = "Name"
description = "Desc"
// And many others
}
}
P.P.S. Sorry for my bad english, it's not my first language

Spring.Caching.AspNetCache - Condition based on ReturnValue - Condition in Spring Expression Language

I use Cache Aspect with ASP.NET Cache. I need create condition based on ReturnValue.
I simplified my problem. I use CacheResult aspect on method wich return simple POCO object.
Here is definition:
public class MyData
{
public string MyProperty { get; set; }
}
public class MyResponse
{
public int MyId { get; set; }
public MyData [] Result { get; set; }
}
I need create condition for cache - Cache result only if MyResponse.MyData.Lenght is bigger then batch limit.
[CacheResult("AspNetCache", "'MyResponse.MyId=' + #id",
Condition = "MyResponse.Result.Length > #batchLimit")]
public MyResponse GetResponse(int id, int batchLimit)
{
Thread.Sleep(5000);
return new MyResponse
{
MyId = 1,
Result =
new MyData[]
{
new MyData {MyProperty = "A"}, new MyData {MyProperty = "B"},
new MyData {MyProperty = "C"},
}
};
}
I tried this definition of condition:
Condition = "MyResponse.Result.Length > #batchLimit"
I got this error:
'MyResponse' node cannot be resolved for the specified context
[Sample.MyResponse].
So I tried second version:
Condition = "'MyResponse.Result.Length' > #batchLimit"
Finished with error:
Cannot compare instances of [System.String] and [System.Int32] because they cannot be coerced to the same type.
I google it I can use keyword ReturnValue something like this:
Condition = "#ReturnValue != null"
But I don't know how I can access to MyResponse.MyData.Length.
the context for the evaluation of the condition expression is the return value, so just do this:
Condition = "Result.Length > #batchLimit"
equivalent to
Condition = "#root.Result.Length > #batchLimit"

Resources