Hello all,
I need some intel and hoping someone may be able to help where I have some strings coming in via JSON this may be easy and not thinking about it right. I have a single enum that I am parsing fine where I do a:
Enum.Parse<CustomerGroup>("GroupA")
I then have a collection of enums where I am having some trouble how to parse it with strings with this Google Protobuf Collection. Here is what it has now without the strings.
Google.Protobuf.Collections.RepeatedField<CustomerOperation> customerOperations = { CustomerOperation.CreateCustomer, CustomerOperation.CreateCustomerGroup };
I need to pass this with strings so the enum values are as follows:
CustomerOperation.CreateCustomer = "CREATE_CUSTOMER"
CustomerOperation.CreateCustomerGroup = "CREATE_CUSTOMER_GROUP"
Any idea how to send this via JSON value it would be key
"customerOperations" : [something here]
and how I can parse that to the enum collection.
Thanks all really appreciate any help hope this makes sense.
It sounds like you're dealing with enum values in Protobuf and how they interact with JSON serialization and deserialization. You're on the right track with Enum.Parse for single enums. For a collection, the process involves a similar idea, but handled through a list or Protobuf's RepeatedField.
Let's break down how to send (serialize) and parse (deserialize) a collection of enums as strings via JSON for your Google.Protobuf.Collections.RepeatedField<CustomerOperation>.
JSON Structure for the Collection:
When a Google.Protobuf.Collections.RepeatedField<CustomerOperation> is serialized to JSON, it typically appears as a JSON array of strings, where each string is the name of the enum member.
Given your enum values:
- CustomerOperation.CreateCustomer maps to "CREATE_CUSTOMER"
- CustomerOperation.CreateCustomerGroup maps to "CREATE_CUSTOMER_GROUP"
The JSON structure for a key "customerOperations" would look like this:
{
"customerOperations": [
"CREATE_CUSTOMER",
"CREATE_CUSTOMER_GROUP",
"ANOTHER_OPERATION_STRING"
]
}
C# Parsing (Deserialization)
There are two main scenarios for parsing this JSON array back into your RepeatedField<CustomerOperation>:
Scenario A: Using Protobuf's Built-in JSON Deserialization (Recommended)
If you have a Protobuf message defined in your .proto file that contains the repeated CustomerOperation field, Protobuf's JsonParser will handle the conversion of string enum values to their corresponding C# enum members automatically.
Example .proto file:
syntax = "proto3";
package Your.App.Namespace;
enum CustomerOperation {
CUSTOMER_OPERATION_UNSPECIFIED = 0;
CREATE_CUSTOMER = 1;
CREATE_CUSTOMER_GROUP = 2;
DELETE_CUSTOMER = 3;
UPDATE_CUSTOMER = 4;
}
message CustomerOperationsMessage {
repeated CustomerOperation operations = 1;
}
Deserialization Code:
Assuming CustomerOperationsMessage and CustomerOperation are generated C# classes from your .proto file:
using Google.Protobuf;
using Your.App.Namespace;
using System;
public class JsonParsingExample
{
public static void Main(string[] args)
{
string jsonString = @"
{
""operations"": [
""CREATE_CUSTOMER"",
""CREATE_CUSTOMER_GROUP"",
""DELETE_CUSTOMER""
]
}";
try
{
var parser = new JsonParser(JsonParser.Settings.Default.WithIgnoreUnknownFields(true));
CustomerOperationsMessage parsedMessage = parser.Parse<CustomerOperationsMessage>(jsonString);
Console.WriteLine("Parsed Customer Operations:");
foreach (var operation in parsedMessage.Operations)
{
Console.WriteLine($"- {operation}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error parsing JSON with Protobuf JsonParser: {ex.Message}");
}
}
}
Scenario B: Manual Parsing of a String Array
If you receive just a raw JSON array of strings (not wrapped in a Protobuf message) and you need to populate a RepeatedField<CustomerOperation>, you'll first deserialize the JSON array into a C# List<string> and then manually convert each string to the enum.
Option B# Deserialization Code:
using Google.Protobuf.Collections;
using Your.App.Namespace;
using System;
using System.Collections.Generic;
using System.Text.Json;
public class ManualParsingExample
{
public static void Main(string[] args)
{
string jsonArrayString = @"[
""CREATE_CUSTOMER"",
""UPDATE_CUSTOMER"",
""INVALID_OPERATION"" // Example of an invalid string
]";
List<string> operationStrings = new List<string>();
try
{
operationStrings = JsonSerializer.Deserialize<List<string>>(jsonArrayString);
Console.WriteLine("Deserialized JSON array to List<string>.");
}
catch (JsonException ex)
{
Console.WriteLine($"Error deserializing JSON array: {ex.Message}");
return;
}
RepeatedField<CustomerOperation> customerOperationsCollection = new RepeatedField<CustomerOperation>();
Console.WriteLine("\nConverting List<string> to RepeatedField<CustomerOperation>...");
foreach (string opString in operationStrings)
{
try
{
CustomerOperation op = (CustomerOperation)Enum.Parse(typeof(CustomerOperation), opString, true);
customerOperationsCollection.Add(op);
Console.WriteLine($"Successfully parsed '{opString}' to {op}");
}
catch (ArgumentException ex)
{
Console.WriteLine($"Warning: Could not parse '{opString}' to CustomerOperation enum. {ex.Message}");
}
}
Console.WriteLine("\nFinal RepeatedField<CustomerOperation> content:");
foreach (var op in customerOperationsCollection)
{
Console.WriteLine($"- {op}");
}
}
}
Serialization (Sending)
Scenario A: Serializing a Protobuf Message
If you have a Protobuf message object containing the RepeatedField<CustomerOperation>, use Google.Protobuf.JsonFormatter to serialize it.
using Google.Protobuf;
using Your.App.Namespace;
using System;
public class JsonSerializationExample
{
public static void Main(string[] args)
{
CustomerOperationsMessage messageToSend = new CustomerOperationsMessage();
messageToSend.Operations.Add(CustomerOperation.CREATE_CUSTOMER);
messageToSend.Operations.Add(CustomerOperation.UPDATE_CUSTOMER);
var jsonFormatter = new JsonFormatter(
JsonFormatter.Settings.Default
.WithFormatEnumsAsInts(false)
);
string serializedJson = jsonFormatter.Format(messageToSend);
Console.WriteLine("Protobuf Message serialized to JSON:\n" + serializedJson);
}
}
Scenario B: Serializing a RepeatedField (or List<string>) directly as a JSON array
If you only need to send the array of enum strings without a full Protobuf message wrapper, you can convert your RepeatedField<CustomerOperation> into a List<string> and then serialize that list using a standard JSON serializer.
using Google.Protobuf.Collections;
using Your.App.Namespace;
using System;
using System.Collections.Generic;
using System.Text.Json;
public class ManualSerializationExample
{
public static void Main(string[] args)
{
RepeatedField<CustomerOperation> customerOperations = new RepeatedField<CustomerOperation>
{
CustomerOperation.CREATE_CUSTOMER_GROUP,
CustomerOperation.DELETE_CUSTOMER
};
List<string> operationsAsStrings = new List<string>();
foreach (var op in customerOperations)
{
operationsAsStrings.Add(op.ToString());
}
string customJsonArray = JsonSerializer.Serialize(operationsAsStrings, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine("Manual List<string> serialized to JSON:\n" + customJsonArray);
var container = new { customerOperations = operationsAsStrings };
string customJsonWithKey = JsonSerializer.Serialize(container, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine("\nManual List<string> under a key serialized to JSON:\n" + customJsonWithKey);
}
}
Summary:
For sending (serializing): Use Google.Protobuf.JsonFormatter if you have a Protobuf message. Otherwise, manually convert your RepeatedField to a List<string> and use System.Text.Json or Newtonsoft.Json to serialize it.
For parsing (deserializing): The most robust and recommended way is to let Protobuf's JsonParser handle it if the JSON represents a full Protobuf message. If you only have a raw JSON array of strings, deserialize it into a List<string> first, and then iterate through it, using Enum.Parse<CustomerOperation>(string_value, true) for each string to populate your RepeatedField.