I have the code below.
The line string content = twitterMsg.text; is creating the error 'Use of unassigned local variable' for twitterMsg. I don't seem able to access my TwitterSearchResponse.results.text fields in my DataContractJsonSerializer<TwitterMain> collection.
TwitterSearchResponse.results is an array (set of object properties) with several string fields attached with names like text and user_info.
Can anyone help with this??
Updated code below. I am still highly confused about why I am not able to iterate over my TwitterSearchResponse.results properly and assign content = twitterMsg.text
For what it's worth, here is my DataContractJsonSerializer method:
String url = String.Format("http://search.twitter.com/search.json?q={0}&rpp=20", Server.UrlEncode(txtSearchFor.Text));
// parse the JSON data
using (MemoryStream ms = new MemoryStream(wc.DownloadData(url)))
{
DataContractJsonSerializer jsonSerializer =
new DataContractJsonSerializer(typeof(TwitterMain));
TwitterSearchResponse = jsonSerializer.ReadObject(ms) as TwitterMain; // read as JSON and map as TwitterOut
}
And here is the original posted code where the issue lies.
public List<MatchCollection> returnMatches(DataContractJsonSerializer<TwitterMain> TwitterSearchResponse)
{
List<MatchCollection> messageLinks = new List<MatchCollection>();
foreach (TwitterResult twitterMsg in TwitterSearchResponse.results)
{
string content = twitterMsg.text;
// capture internet protocol pre-fixed words from message
string pattern = #"...";
messageLinks.Add(Regex.Matches(content, pattern, RegexOptions.IgnoreCase));
// capture #username twitter users from message
string atUsernamePattern = #"#([a-zA-Z0-9-_]+)";
MatchCollection PeopleMatches = Regex.Matches(content, atUsernamePattern, RegexOptions.IgnoreCase);
}
return messageLinks;
}
I suspect it's actually reporting the use of the unassigned local variable MessageLinks. Your use of twitterMsg looks fine.
So, the big question is: what do you want to return if there aren't any results? If you're happy returning null, just assign the value when you declare MessageLinks.
Next question: do you really only want to return the last MatchCollection you find? That's what the current behaviour is: you're looping over all the variables, setting the same local variable each time (i.e. replacing the previous value) and then returning that last value.
Final question: any reason why you've got a camel-cased method name (returnMatches), a Pascal-cased local variable (MessageLinks), a Pascal-cased parameter name (TwitterSearchResponse) and a camel-cased property (text)? I would assume that text is due to it coming from JSON that way - but it's a good idea to follow normal .NET naming conventions otherwise.
Related
at line 161,I want to insert my text in parameter t,but it won't change when i debug it.although the parameter tmp had alredy changed.
I want to change this Text in UI,when my parameter t changes.
With respect to your specific issue, Insert is defined as:
public string Insert (int startIndex, string value);
and returns a new string. In C#, strings aren't modified, new strings are created. In this way, they act like a value type, even though they're a reference type. In other words, once a string is created, it is never modified - it's 'immutable'. So, you need to store your newly created string.
In cases like this, I like to use the string interpolation, as it allows me to get a slightly clearer representation of what the final string will look like.
var tmp = System.Text.Encoding.UTF8.GetString ( e.Message );
t.text = $"{tmp}\n{t.text}"; // Note that a newline is represented as \n
Or, if you add the System.Text namespace; you could reduce it down to:
using System.Text;
...
t.text = $"{Encoding.UTF8.GetString ( e.Message )}\n{t.text}";
The string type in c# is immutable, therefore Insert returns a new string instead of modifying the current one.
Do:
t = t.text.Insert(0, tmp + "//n");
See also
How to modify string contents in C#
the interpolated string is easy, just a string lead with $ sign. But what if the string template is coming from outside of your code. For example assume you have a XML file containing following line:
<filePath from="C:\data\settle{date}.csv" to="D:\data\settle{date}.csv"/>
Then you can use LINQ to XML read the content of the attributes in.
//assume the ele is the node <filePath></filePath>
string pathFrom = ele.Attribute("from").value;
string pathTo = ele.Attibute("to").value;
string date = DateTime.Today.ToString("MMddyyyy");
Now how can I inject the date into the pathFrom variable and pathTo variable?
If I have the control of the string itself, things are easy. I can just do var xxx=$"C:\data\settle{date}.csv";But now, what I have is only the variable that I know contains the placeholder date
String interpolation is a compiler feature, so it cannot be used at runtime. This should be clear from the fact that the names of the variables in the scope will in general not be availabe at runtime.
So you will have to roll your own replacement mechanism. It depends on your exact requirements what is best here.
If you only have one (or very few replacements), just do
output = input.Replace("{date}", date);
If the possible replacements are a long list, it might be better to use
output = Regex.Replace(input, #"\{\w+?\}",
match => GetValue(match.Value));
with
string GetValue(string variable)
{
switch (variable)
{
case "{date}":
return DateTime.Today.ToString("MMddyyyy");
default:
return "";
}
}
If you can get an IDictionary<string, string> mapping variable names to values you may simplify this to
output = Regex.Replace(input, #"\{\w+?\}",
match => replacements[match.Value.Substring(1, match.Value.Length-2)]);
You can't directly; the compiler turns your:
string world = "world";
var hw = $"Hello {world}"
Into something like:
string world = "world";
var hw = string.Format("Hello {0}", world);
(It chooses concat, format or formattablestring depending on the situation)
You could engage in a similar process yourself, by replacing "{date" with "{0" and putting the date as the second argument to a string format, etc.
SOLUTION 1:
If you have the ability to change something on xml template change {date} to {0}.
<filePath from="C:\data\settle{0}.csv" to="D:\data\settle{0}.csv" />
Then you can set the value of that like this.
var elementString = string.Format(element.ToString(), DateTime.Now.ToString("MMddyyyy"));
Output: <filePath from="C:\data\settle08092020.csv" to="D:\data\settle08092020.csv" />
SOLUTION 2:
If you can't change the xml template, then this might be my personal course to go.
<filePath from="C:\data\settle{date}.csv" to="D:\data\settle{date}.csv" />
Set the placeholder like this.
element.Attribute("to").Value = element.Attribute("to").Value.Replace("{date}", DateTime.Now.ToString("MMddyyyy"));
element.Attribute("from").Value = element.Attribute("from").Value.Replace("{date}", DateTime.Now.ToString("MMddyyyy"));
Output: <filePath from="C:\data\settle08092020.csv" to="D:\data\settle08092020.csv" />
I hope it helps. Kind regards.
If you treat your original string as a user-input string (or anything that is not processed by the compiler to replace the placeholder, then the question is simple - just use String.Replace() to replace the placehoder {date}, with the value of the date as you wish. Now the followup question is: are you sure that the compiler is not substituting it during compile time, and leaving it untouched for handling at the runtime?
String interpolation allows the developer to combine variables and text to form a string.
Example
Two int variables are created: foo and bar.
int foo = 34;
int bar = 42;
string resultString = $"The foo is {foo}, and the bar is {bar}.";
Console.WriteLine(resultString);
Output:
The foo is 34, and the bar is 42.
I have a json as string. I want to convert it into an object. But during conversion, everything is fine, except i get an extra braces outside of the object. That is not a valid json.
string st = "{\"Category\":\"test\"}";
var someType = JsonConvert.DeserializeObject(st);
//output of someType is {{"Category": "test"}}
//expected output {"Category": "test"}
I tried "JObject.Parse()" too. But the result is the same. It adds extra braces to the object.
I want the output as an object compulsorily.
Is there anything that i'm doing wrong? Am i missing something?
In the context of what you're asking, JsonConver.DeserializeObject(st) is doing exactly what you're asking it to do. You're asking it to convert a string representation of the "object" {"Category": "test"} to a json object. The problem with your approach, is that the compiler does not know how to interpret that string as anything other than an object, so it wraps it in a JSON object.
To get the result you're looking for, without declaring a POCO (i.e. deserializing an anonymous type), you'd need to do something like this
var definition = new { Category = "" };
var data = #"{'Category':'Test'}";
var me = JsonConvert.DeserializeAnonymousType(data, definition);
Console.WriteLine(me);
Adding another solution, given what was asked for in the comments.
dynamic deserialized = JObject.Parse("{\"Category\":\"test\"}");
In the code snippet below, the JSON string in the commented out jsonString variable is valid while the uncommented out one causes JObject.Parse to throw a JsonReaderException with the message:
After parsing a value an unexpected character was encountered: e. Path 'Key', line 1, position 15.
var jsonString = "{\"Key\":\"Value \"extra\" \"}";
//var jsonString = "{\"Key\":\"Value \\\"extra\\\" \"}";
JObject.Parse(jsonString);
Are there any methods available in Newtonsoft.Json or elsewhere that can transform a JSON string to make it valid?
No, because NewtonSoft cannot guess what you want. E.g. is extra a new key and did you just ommit a comma or is it part of the previous value, or is it just something that can be ignored. It would be better to have the thing you are consuming the json from construct valid json.
Using Regex might help you to resolve the existing JSON you have. If you can control how subsequent JSON is generated, you really should fix it at that point.
This solution counts the value as existing from the first " after a "key":, through to the last " before a , or a }, and then it reserializes the value to ensure that it is correctly escaped. If it finds ",, it expects it to be followed by another key ("key":). This is in an attempt to avoid red herrings (i.e. {"key": "test "," value"}) which might otherwise confuse it.
private static string FixJson(string json)
{
var regex = new Regex("\"(?<key>.*?)\"\\W?:\\W?\"(?<value>.*?)\"(?=,\".*?\"\\W?:|}$)");
return regex.Replace(json, new MatchEvaluator(m => {
var key = m.Groups["key"].Value;
var val = m.Groups["value"].Value;
return string.Format("\"{0}\":{1}", key, JsonConvert.SerializeObject(val));
}));
}
Disclaimer: It's a regular expression, it's not foolproof, and if your JSON is more broken than you have indicated, it will probably spit out broken JSON, or incorrect values, so use it at your own risk.
Try it online
I'm having some issues with the string comparison of a string the is received by Request.queryString and a line from a file .resx.
The code receive Request.queryString to a variable named q, then it goes to a function to compare if a line has q value in it:
while ((line = filehtml.ReadLine()) != null)
{
if (line.ToLower().Contains(q.ToLower().ToString()))
HttpContext.Current.Response.Write("<b>Content found!</b>");
else
HttpContext.Current.Response.Write("<b>Content not found!</b>");
}
As it's a search in static files, special characters must be consider and seraching for: Iberê for example, isn't returning true because the .Contains, .IndexOf or .LastindexOf is comparing: iberê, that is coming from q, with iberê that is coming from the line.
Consider that I already tried to use ResXResourceReader (which can't be found by Visual Studio), ResourceReader and ResourceManager (these I couldn't set a static file by the path to be read).
EDIT:
Problem solved. There was a instance of SpecialChars, overwriting q value with EntitiesEncode method
The problem is that the ê character is escaped in both strings. So if you did something like this, it wouldn't work:
string line = "sample iberê text";
string q = "iberê";
if (line.Contains(q)) {
// do something
}
You need to unscape the strings. Use HttpUtility in the System.Web assembly. This will work:
line = System.Web.HttpUtility.HtmlDecode(line);
q = System.Web.HttpUtility.HtmlDecode(q);
if (line.Contains(q)) {
// do something
}
As suggested by #r3bel below, if you're using .net 4 or above you can also use System.Net.WebUtility.HtmlDecode, so you don't need an extra assembly reference.