英文:
Convert non-json string version of object to object
问题
将非 JSON 字符串转换为 DiscriminatorTags
结构类型,你可以使用自定义逻辑,解析字符串并设置结构的属性。在你的 DiscriminatorTagsBinder
类的 BindModelAsync
方法中,替换以下行:
var x = JsonSerializer.Deserialize<DiscriminatorTags>(valueProviderResult.FirstValue);
使用以下逻辑:
var stringValue = valueProviderResult.FirstValue;
if (stringValue != null)
{
// Assuming the format is consistent, you can implement your parsing logic here
var tagsStartIndex = stringValue.IndexOf("tags: [");
var tagsEndIndex = stringValue.IndexOf("]", tagsStartIndex);
if (tagsStartIndex != -1 && tagsEndIndex != -1)
{
var tagsSubstring = stringValue.Substring(tagsStartIndex + 7, tagsEndIndex - tagsStartIndex - 7);
var tagsArray = tagsSubstring.Split(',').Select(tag => int.Parse(tag.Trim())).ToList();
var discriminatorStartIndex = stringValue.IndexOf("discriminator: ");
var discriminatorEndIndex = stringValue.IndexOf(")", discriminatorStartIndex);
if (discriminatorStartIndex != -1 && discriminatorEndIndex != -1)
{
var discriminatorSubstring = stringValue.Substring(discriminatorStartIndex + 15, discriminatorEndIndex - discriminatorStartIndex - 15);
var selected = stringValue.Contains("selected: true");
var discriminatorTags = new DiscriminatorTags(tagsArray, discriminatorSubstring, selected);
// Now 'discriminatorTags' holds the parsed object
}
}
}
这样,你就可以手动解析非 JSON 字符串并构建 DiscriminatorTags
结构对象。
英文:
How do I convert a string version of an object that is not JSON, to the object type?
I'm creating a custom model binder for this struct so that I can send it as a Query Parameter:
[Serializable]
[ModelBinder(BinderType = typeof(DiscriminatorTagsBinder))]
public struct DiscriminatorTags : IDiscriminatorTags
{
public DiscriminatorTags(List<int> tags, string discriminator, bool selected)
{
this.Tags = tags;
this.Discriminator = discriminator;
this.Selected = selected;
}
[Required]
public List<int> Tags { get; set; }
[Required]
public string Discriminator { get; set; }
[Required]
public bool Selected { get; set; }
}
The binder:
public class DiscriminatorTagsBinder : IModelBinder
{
public DiscriminatorTagsBinder()
{
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
// Try to fetch the value of the argument by name
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
var x = JsonSerializer.Deserialize<DiscriminatorTags>(valueProviderResult.FirstValue);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);
var value = valueProviderResult.FirstValue;
// Check if the argument value is null or empty
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
bindingContext.Result = ModelBindingResult.Success(valueProviderResult);
return Task.CompletedTask;
}
}
The value to deserialize is actually not JSON, it is a string version of the object:
> "DiscriminatorTags(tags: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
> 14, 15, 16, 17, 18, 900], selected: true, discriminator: GroceryItm)"
So I am getting a JsonException when I do this: var x = JsonSerializer.Deserialize<DiscriminatorTags>(valueProviderResult.FirstValue);
How do I convert the non-json string to the DiscriminatorTags
struct type?
答案1
得分: 4
这可能听起来很明显,但你需要手动解析你的字符串。这里没有免费的午餐。像这样的代码可以帮助你入门:
var str = "DiscriminatorTags(tags: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 900], selected: true, discriminator: GroceryItm)";
var matches = Regex.Matches(str, @"(tags:\s*\[(.*)\])|(selected:\s(true|false))|(discriminator:\s\w*)", RegexOptions.IgnoreCase);
var tagsMatch = matches[0].ValueSpan;
var bracketStartIndex = tagsMatch.IndexOf('[');
var tagsList = tagsMatch.Slice(bracketStartIndex + 1, tagsMatch.LastIndexOf(']') - 1 - bracketStartIndex);
var list = new List<int>();
foreach (var match in Regex.EnumerateMatches(tagsList, "[0-9]+"))
{
list.Add(Convert.ToInt32(tagsList.Slice(match.Index, match.Length).ToString()));
}
var selectedMatch = matches[1];
var isSelected = Regex.Match(selectedMatch.Value, "true|false", RegexOptions.IgnoreCase);
var discriminatorMatch = matches[2].ValueSpan;
var discriminator = discriminatorMatch[(discriminatorMatch.IndexOf(':') + 1)..].Trim();
你需要加强它来防止缺少值等情况,还要使用已编译的正则表达式实例。
英文:
This might sound obvious but you're going to have to manually parse your string. There is no free lunch here. Something like this could get you started:
var str = "DiscriminatorTags(tags: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 900], selected: true, discriminator: GroceryItm)";
var matches = Regex.Matches(str, @"(tags:\s*\[(.*)\])|(selected:\s(true|false))|(discriminator:\s\w*)", RegexOptions.IgnoreCase);
var tagsMatch = matches[0].ValueSpan;
var bracketStartIndex = tagsMatch.IndexOf('[');
var tagsList = tagsMatch.Slice(bracketStartIndex + 1, tagsMatch.LastIndexOf(']') - 1 - bracketStartIndex);
var list = new List<int>();
foreach (var match in Regex.EnumerateMatches(tagsList, "[0-9]+"))
{
list.Add(Convert.ToInt32(tagsList.Slice(match.Index, match.Length).ToString()));
}
var selectedMatch = matches[1];
var isSelected = Regex.Match(selectedMatch.Value, "true|false", RegexOptions.IgnoreCase);
var discriminatorMatch = matches[2].ValueSpan;
var discriminator = discriminatorMatch[(discriminatorMatch.IndexOf(':') + 1)..].Trim();
You would need to harden it to guard against missing values etc. and also use a compiled instance for the Regex
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论