2010-05-11 17 views
2

J'ai un client Java actif qui communique avec Google via des messages sérialisés ProtoBuf. J'essaie actuellement de traduire ce client en C#.Sérialisation des champs non obligatoires dans protobuf-net

J'ai un fichier .proto où le paramètre appId est une chaîne optionnelle. Sa valeur par défaut dans la représentation C# générée par la bibliothèque protobuf-net est une chaîne vide, tout comme dans la représentation java du même fichier.

message AppsRequest { 
    optional AppType appType = 1; 
    optional string query = 2; 
    optional string categoryId = 3; 
    optional string appId = 4; 
    optional bool withExtendedInfo = 6; 
} 

Je trouve que lorsque je mets explicitement appId à "" dans le client java, le client cesse de fonctionner (403 Bad Request de Google). Lorsque je définis explicitement appId à null dans le client Java, tout fonctionne, mais uniquement parce que hasAppId est défini sur false (je ne suis pas certain de la façon dont cela affecte la sérialisation).

Dans le client C#, j'obtiens toujours 403 réponses. Je ne vois aucune logique derrière la distinction entre ne pas définir une valeur, et définir la valeur par défaut, qui semble faire toute la différence dans le client Java. Étant donné que la sortie est toujours un flux binaire, je ne suis pas sûr que les messages Java réussis sont sérialisés avec une chaîne vide, ou pas sérialisés du tout.

Dans le client C#, j'ai essayé d'installer IsRequired true sur l'attribut ProtoMember, pour les forcer à sérialiser, et je l'ai essayé de définir la valeur par défaut à null, et définissez explicitement "", donc je suis tout à fait certain que j'ai essayé configuration où la valeur est en cours de sérialisation. J'ai également joué avec ProtoBuf.ProtoIgnore et à un moment donné, en supprimant le paramètre appId, mais je n'ai pas pu éviter les erreurs 403 en C#.

J'ai essayé de copier manuellement la chaîne sérialisée de Java, et cela a résolu mes problèmes, donc je suis certain que le reste de la requête HTTP fonctionne, et l'erreur peut être tracée à l'objet sérialisé.

Mon sérialisation est simplement ceci:

var clone = ProtoBuf.Serializer.DeepClone(request); 

MemoryStream ms = new MemoryStream(2000); 
ProtoBuf.Serializer.Serialize(ms, clone); 

var bytearr = ms.ToArray(); 
string encodedData = Convert.ToBase64String(bytearr); 

J'avoue ne pas être tout à fait sûr de ce que DeepClone fait. J'ai essayé à la fois avec et sans ...

Répondre

1

Il semble que nous voulons le forcer à être exclu; Pour essayer d'abord, vous pouvez essayer d'utiliser l'option "detectmissing" dans la génération de code. Ceci est possible à partir de l'IDE et de la ligne de commande, mais différemment (faites moi savoir ce que vous utilisez et j'en ajouterai plus).

Une autre option similaire consiste à ajouter (dans une classe partielle) un bool {memberName}Specified {get;set;}. Il y a un rapport ouvert d'une anomalie impliquant des chaînes vides par défaut, que je regarde.

+1

Bravo pour la réponse rapide. J'ai généré le code à partir de la ligne de commande. La propriété '* Specified' semble n'avoir aucun effet sur le résultat, que je le mette à' true' ou 'false'. Même chose pour la méthode 'ShouldSerialize *', comme suggéré ici: http://stackoverflow.com/questions/1379332/protobuf-net-not-serializing-zero –

+0

J'ai trouvé un morceau de code dans le sérialiseur java vérifie 'if (hasAppId()) {output.writeString (4, getAppId()); } 'donc il semble effectivement que l'exclure complètement de la sortie sérialisée est ce que je veux faire. –

+0

@David Hedlund OK; J'ai ton exemple - je verrai ce que je peux faire avec. Pour info, avez-vous un exemple de données simple avec la sortie java, donc je peux confirmer le résultat? –