I'm getting this on console.log;
2014-08-13 11:55:11.877 Wevo[14264:1830541] artist name: (
"Vance Joy"
)
How do I unwrap it so its just the string?
The problem comes because I'm parsing json that looks like this:
output = {
contributor = {
"/music/recording/artist" = [
{
mid = "/m/026hdj4";
name = "Marie-Mai";
}
];
};
};
notice how the mid is wrapped in an array?
So it gets converted to an object literal somewhere
I'm setting the value using:
_artistName = [[attributes[#"output"][#"contributor"][#"/music/recording/artist"] valueForKeyPath:#"name"] copy];
Why are you using valueForKeyPath:? If you use
_artistName = attributes[#"output"][#"contributor"][#"/music/recording/artist"][0][#"name"];
it should come out correctly.
Edit: For future viewers, one off lines like this will work. However, for a more maintainable and debuggable app, I would recommend splitting up the lines to extract only one object per line. That way, if something breaks, the debugger will be a larger help.
For apps where you deal with more JSON than just a one off, I would recommend creating model objects and pulling your JSON into those. There are libraries on github that could also help you there with model objects.
Related
How to populate the value of this variable:
private val _urlList = MutableLiveData<List<Url>>()
of type Url:
data class Url(
val imgSrcUrl: String
)
with the incoming list of url strings from a firebase call?
Here is where the magic happens:
private fun getData(){
viewModelScope.launch {
try {
getImagesUrl {
"Here where I need to set the value of the variable to a listOf(it) with it being strings
of urls retrieved from firebase storage"
}
}catch (e: Exception){
"Handling the error"
}
}
}
Edit
The map function #dominicoder provided solved my problem, answer accepted.
Thank you all for your help
Your question is unclear because you're showing a live data of a single Url object but asking to stuff it with a list of strings. So first, your live data object needs to change to a list of Urls:
private val _urlList = MutableLiveData<List<Url>>()
Then, assuming getImagesUrl yields a list of strings, if I understood you correctly, then you would map that to a list of Urls:
getImagesUrl { listOfImageUrlStrings ->
_urlList.value = listOfImageUrlStrings.map { imageUrlString -> Url(imageUrlString) }
}
If that does not answer your question, you really need to review it and clarify.
You can set values on the MutableLiveDataObject in two ways (depends on what you're doing).
Setting the value as normal from the UI thread can be done with:
myLiveData.value = myobject
If you're setting it from a background thread like you might in a coroutine with a suspended function or async task etc then use:
myLiveData.postValue(myObject)
It's not clear from your question whether the LiveData is meant to hold a list as you mention both lists and single values. But your LiveData holds a set the values as a collection like a list, set or map. It's can be treated as a whole object so adding a value later needs to have the whole collection set again like:
myLiveData.value = mutableListOf<Url>()
//Response received and object created
myLiveData.value = myLiveData.value.apply {
add(myObject)
}
Or if the value is mutable updating the existing value (preferred as it's cleaner):
myLiveData.value.add(myObject)
The problem with that approach is you're exposing the map as a mutable/writeable object. Allowing accessors to change the values which you might not want.
How can i get my json from web api to format only value or null for Option types and Discriminated Unions preferably using Newtonsoft.
I am currently using Newtonsoft and only have to add this to web api for it to work:
config.Formatters.JsonFormatter.SerializerSettings <- new JsonSerializerSettings()
When i consume the data on my side, i can easily convert it back to an F# item using: JsonConvert.DeserializeObject<'a>(json)
The api will be consumed by NON .NET clients as well so i would like a more standard formatted json result.
I would like to to fix my issue, w/o having to add code or decorators to all of my records/DU in order for it to work. I have lots of records with lots of properties, some are Option.
ex (this is how DU is serializing):
// When value
"animal": {
"case": "Dog"
}
// When no value
"animal": null
This is what I need:
// When value
"animal": "Dog"
// When no value
"animal": null
This is how an Option type is serializing:
"DocumentInfo": {
"case": "Some",
"fields": [
{
"docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
"docType": "Monkey Business",
"docName": "mb.doc",
"docContent": "why cant it just give me the values?"
}
]
}
This is what I need:
"DocumentInfo": {
"docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
"docType": "Monkey Business",
"docName": "mb.doc",
"docContent": "why cant it just give me the values?"
}
Thank you :-)
You could try using Chiron. I haven't used it myself so I can't give you an extensive example, but https://neoeinstein.github.io/blog/2015/12-13-chiron-json-ducks-monads/index.html has some bits of sample code. (And see https://neoeinstein.github.io/blog/2016/04-02-chiron-computation-expressions/index.html as well for some nicer syntax). Basically, Chiron knows how to serialize and deserialize the basic F# types (strings, numbers, options, etc.) already, and you can teach it to serialize any other type by providing that type with two static methods, ToJson and FromJson:
static member ToJson (x:DocumentInfo) = json {
do! Json.write "docId" x.docId
do! Json.write "docType" x.docType
do! Json.write "docName" x.docName
do! Json.write "docContent" x.docContent
}
static member FromJson (_:DocumentInfo) = json {
let! i = Json.read "docId"
let! t = Json.read "docType"
let! n = Json.read "docName"
let! c = Json.read "docContent"
return { docId = i; docType = t; docName = n; docContent = c }
}
By providing those two static methods on your DocumentInfo type, Chiron will automatically know how to serialize a DocumentInfo option. At least, that's my understanding -- but the Chiron documentation is sadly lacking (by which I mean literally lacking: it hasn't been written yet), so I haven't really used it myself. So this may or may not be the answer you need, but hopefully it'll be of some help to you even if you don't end up using it.
I have found the solution that allows me to use Newtonsoft (JSON.NET), apply custom converters for my types where needed and not require any changes to my DU's or Records.
The short answer is, create a custom converter for Json.Net and use the Read/Write Json overrides:
type CustomDuConverter() =
inherit JsonConverter() (...)
Unfortunately the ones I have found online that were already created doesn't work as is for my needs listed above, but will with slight modification. A great example is to look at: https://gist.github.com/isaacabraham/ba679f285bfd15d2f53e
To apply your custom serializer in Web Api for every call, use:
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new CustomDuConverter())
To deserialize use (example that will deserialize to DU):
JsonConvert.DeserializeObject<Animal>("Dog", customConverter)
ex:
type Animal = Dog | Cat
json:
"animal": "Dog"
This will allow you to create a clean Api for consumers and allow you to consume 3rd party Json data into your types that use Option, etc.
I am using Google diff-match-patch JAVA plugin to create patch between two JSON strings and storing the patch to database.
diff_match_patch dmp = new diff_match_patch();
LinkedList<Patch> diffs = dmp.patch_make(latestString, originalString);
String patch = dmp.patch_toText(diffs); // Store patch to DB
Now is there any way to use this patch to re-create the originalString by passing the latestString?
I google about this and found this very old comment # Google diff-match-patch Wiki saying,
Unpatching can be done by just looping through the diff, swapping
DIFF_INSERT with DIFF_DELETE, then applying the patch.
But i did not find any useful code that demonstrates this. How could i achieve this with my existing code ? Any pointers or code reference would be appreciated.
Edit:
The problem i am facing is, in the front-end i am showing a revisions module that shows all the transactions of a particular fragment (take for example an employee details), like which user has updated what details etc. Now i am recreating the fragment JSON by reverse applying each patch to get the current transaction data and show it as a table (using http://marianoguerra.github.io/json.human.js/). But some JSON data are not valid JSON and I am getting JSON.parse error.
I was looking to do something similar (in C#) and what is working for me with a relatively simple object is the patch_apply method. This use case seems somewhat missing from the documentation, so I'm answering here. Code is C# but the API is cross language:
static void Main(string[] args)
{
var dmp = new diff_match_patch();
string v1 = "My Json Object;
string v2 = "My Mutated Json Object"
var v2ToV1Patch = dmp.patch_make(v2, v1);
var v2ToV1PatchText = dmp.patch_toText(v2ToV1Patch); // Persist text to db
string v3 = "Latest version of JSON object;
var v3ToV2Patch = dmp.patch_make(v3, v2);
var v3ToV2PatchTxt = dmp.patch_toText(v3ToV2Patch); // Persist text to db
// Time to re-hydrate the objects
var altV3ToV2Patch = dmp.patch_fromText(v3ToV2PatchTxt);
var altV2 = dmp.patch_apply(altV3ToV2Patch, v3)[0].ToString(); // .get(0) in Java I think
var altV2ToV1Patch = dmp.patch_fromText(v2ToV1PatchText);
var altV1 = dmp.patch_apply(altV2ToV1Patch, altV2)[0].ToString();
}
I am attempting to retrofit this as an audit log, where previously the entire JSON object was saved. As the audited objects have become more complex the storage requirements have increased dramatically. I haven't yet applied this to the complex large objects, but it is possible to check if the patch was successful by checking the second object in the array returned by the patch_apply method. This is an array of boolean values, all of which should be true if the patch worked correctly. You could write some code to check this, which would help check if the object can be successfully re-hydrated from the JSON rather than just getting a parsing error. My prototype C# method looks like this:
private static bool ValidatePatch(object[] patchResult, out string patchedString)
{
patchedString = patchResult[0] as string;
var successArray = patchResult[1] as bool[];
foreach (var b in successArray)
{
if (!b)
return false;
}
return true;
}
I'm new to Javascript and the google-api and still struggling with casting and basic functionality.
I'm trying to copy a column of strings harvested from a sheet to another array for manipulation and running into various errors. So far I have tried the following ( that have not generated straight up syntax errors )...
// Character VALIDATION function
function validateCharacter(characterName) {
var sheetName = ("!" + characterName);
var characterSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
// characterData array will hold the values from the characters sheet
var dataRange=characterSheet.getDataRange();
var characterData = dataRange.getValues();
var Physicals;
Physicals.copyofrange(characterData,[14][0],[31][0]);
console.log(Physicals);
}
and
// Character VALIDATION function
function validateCharacter(characterName) {
var sheetName = ("!" + characterName);
var characterSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
// characterData array will hold the values from the characters sheet
var dataRange=characterSheet.getDataRange();
var characterData = dataRange.getValues();
var Physicals;
for (i=0;i<17;i++){
Physicals[i]=characterData[i+13][0];
}
console.log(Physicals);
}
I know that Java handles strings as pointers, but I'm not clear if Javascript does and I thought of the for loop first but I'm getting
TypeError: Cannot set property "0.0" of undefined to "Agile". (line 40).
when I do that. I'm assuming I'm missing something... dimensional? about the declaration of the array to be copied to but I can't figure out what. I've looked over various solutions involving Java declarations for arrays but none of those seem to apply or be allowed in the google-spreadsheets-api Javascript. It seemed to not even acknowledge the String declaration when I tried String[]=new String etc. Frankly I don't care how it's implemented just so it works. Efficiency isn't a big concern on this project. Thank you.
OK, figured it out. After seeing all the Java things that Javascript does not support, I found some documentation specifically on Javascript string handling and figured out I have to cast Physicals as an empty array then "push" the values into it in the loop rather than assigning them with = statements, as such.
// Character VALIDATION function
function validateCharacter(characterName) {
var sheetName = ("!" + characterName);
var characterSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
// characterData array will hold the values from the characters sheet
var dataRange=characterSheet.getDataRange();
var characterData = dataRange.getValues();
var Physicals=[];
for (i=0;i<17;i++){
Physicals.push(characterData[i+13][0]);
}
return(Physicals);
}
Knowing the distinction between Java, Javascript, and Guava actually helped a great deal since they seem to have wildly different function handling despite similar names and common ancestry.
I'm using PetaPoco T4 Template (http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx), It always converting table names, for example it converts a table named "Media" to "Medium". Have you any idea how can I make it to stop doing that?
Thanks
In your .Database.tt file you can tweak the class names to your liking for each table:
tables["Media"].ClassName = "Media";
I don't know of a way to turn this off everywhere. I believe it is a remnant from the SubSonic inflector. In the SchemaReader classes you will see a call like this:
tbl.ClassName=Inflector.MakeSingular(tbl.CleanName);
You could try changing that to
tbl.ClassName=tbl.CleanName;
To prevent that, I put always this piece of code in the Database.tt file:
// Read schema
var tables = LoadTables();
foreach(Table t in tables)
{
if(!t.Name.ToLower().StartsWith("tablePrefix_"))
{
// Filter tables by prefix
t.Ignore = true;
}
else
{
// This do the trick discussed here
t.ClassName = t.CleanName;
}
}